package manifest import ( "bytes" "encoding/json" ) // Argument is a special struct that was made to handle a mixed-typed array // of arguments in a manifest. // // An argument in a manifest could be: // - a single string // - an object consists of rules array field and a value field that could be // a single string or an array of strings. type Argument struct { Rules []Rule `json:"rules"` Value []string `json:"value"` } // CheckRules returns true if all rules passed and a feature set in a rule if // applicable, a FeatureUnknown otherwise. func (a Argument) CheckRules() (ok bool, feature Feature) { feature = FeatureUnknown for _, r := range a.Rules { ok, feature = r.Check() if !ok { return false, feature } } return true, feature } // UnmarshalJSON had to be implemented because of mixed-typed nature of an // arguments array in a manifest. func (a *Argument) UnmarshalJSON(data []byte) error { if data[0] == '"' { a.Value = append(a.Value, string(data[1:len(data)-1])) } else if data[0] == '{' && bytes.Contains(data, []byte("value\": \"")) { singleValArg := struct { Rules []Rule `json:"rules"` Value string `json:"value"` }{} if err := json.Unmarshal(data, &singleValArg); err != nil { return err } a.Rules = singleValArg.Rules a.Value = append(a.Value, singleValArg.Value) } else if data[0] == '{' { multiValArg := struct { Rules []Rule `json:"rules"` Value []string `json:"value"` }{} if err := json.Unmarshal(data, &multiValArg); err != nil { return err } a.Rules = multiValArg.Rules a.Value = multiValArg.Value } return nil }