11package genericresource
22
33import (
4+ "encoding/csv"
45 "fmt"
56 "strconv"
67 "strings"
@@ -12,36 +13,99 @@ func newParseError(format string, args ...interface{}) error {
1213 return fmt .Errorf ("could not parse GenericResource: " + format , args ... )
1314}
1415
15- // Parse parses the GenericResource resources given by the arguments
16- func Parse (cmd string ) ([]* api.GenericResource , error ) {
17- var rs []* api.GenericResource
16+ // discreteResourceVal returns an int64 if the string is a discreteResource
17+ // and an error if it isn't
18+ func discreteResourceVal (res string ) (int64 , error ) {
19+ return strconv .ParseInt (res , 10 , 64 )
20+ }
21+
22+ // allNamedResources returns true if the array of resources are all namedResources
23+ // e.g: res = [red, orange, green]
24+ func allNamedResources (res []string ) bool {
25+ for _ , v := range res {
26+ if _ , err := discreteResourceVal (v ); err == nil {
27+ return false
28+ }
29+ }
30+
31+ return true
32+ }
33+
34+ // ParseCmd parses the Generic Resource command line argument
35+ // and returns a list of *api.GenericResource
36+ func ParseCmd (cmd string ) ([]* api.GenericResource , error ) {
37+ if strings .Contains (cmd , "\n " ) {
38+ return nil , newParseError ("unexpected '\\ n' character" )
39+ }
40+
41+ r := csv .NewReader (strings .NewReader (cmd ))
42+ records , err := r .ReadAll ()
43+
44+ if err != nil {
45+ return nil , newParseError ("%v" , err )
46+ }
47+
48+ if len (records ) != 1 {
49+ return nil , newParseError ("found multiple records while parsing cmd %v" , records )
50+ }
1851
19- for _ , term := range strings .Split (cmd , ";" ) {
52+ return Parse (records [0 ])
53+ }
54+
55+ // Parse parses a table of GenericResource resources
56+ func Parse (cmds []string ) ([]* api.GenericResource , error ) {
57+ tokens := make (map [string ][]string )
58+
59+ for _ , term := range cmds {
2060 kva := strings .Split (term , "=" )
2161 if len (kva ) != 2 {
22- return nil , newParseError ("incorrect term %s, missing '=' or malformed expr" , term )
62+ return nil , newParseError ("incorrect term %s, missing" +
63+ " '=' or malformed expression" , term )
2364 }
2465
2566 key := strings .TrimSpace (kva [0 ])
2667 val := strings .TrimSpace (kva [1 ])
2768
28- u , err := strconv .ParseInt (val , 10 , 64 )
29- if err == nil {
69+ tokens [key ] = append (tokens [key ], val )
70+ }
71+
72+ var rs []* api.GenericResource
73+ for k , v := range tokens {
74+ if u , ok := isDiscreteResource (v ); ok {
3075 if u < 0 {
31- return nil , newParseError ("cannot ask for negative resource %s" , key )
76+ return nil , newParseError ("cannot ask for" +
77+ " negative resource %s" , k )
3278 }
33- rs = append (rs , NewDiscrete (key , u ))
79+
80+ rs = append (rs , NewDiscrete (k , u ))
3481 continue
3582 }
3683
37- if len (val ) > 2 && val [0 ] == '{' && val [len (val )- 1 ] == '}' {
38- val = val [1 : len (val )- 1 ]
39- rs = append (rs , NewSet (key , strings .Split (val , "," )... )... )
84+ if allNamedResources (v ) {
85+ rs = append (rs , NewSet (k , v ... )... )
4086 continue
4187 }
4288
43- return nil , newParseError ("could not parse expression '%s'" , term )
89+ return nil , newParseError ("mixed discrete and named resources" +
90+ " in expression '%s=%s'" , k , v )
4491 }
4592
4693 return rs , nil
4794}
95+
96+ // isDiscreteResource returns true if the array of resources is a
97+ // Discrete Resource.
98+ // e.g: res = [1]
99+ func isDiscreteResource (values []string ) (int64 , bool ) {
100+ if len (values ) != 1 {
101+ return int64 (0 ), false
102+ }
103+
104+ u , err := discreteResourceVal (values [0 ])
105+ if err != nil {
106+ return int64 (0 ), false
107+ }
108+
109+ return u , true
110+
111+ }
0 commit comments