| // Copyright 2023 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package pythonconfig |
| |
| import ( |
| "fmt" |
| "sort" |
| "strings" |
| ) |
| |
| // StringSet satisfies the flag.Value interface. It constructs a set backed by |
| // a hashmap by parsing the flag string value using the provided separator. |
| type StringSet struct { |
| set map[string]struct{} |
| separator string |
| } |
| |
| // NewStringSet constructs a new StringSet with the given separator. |
| func NewStringSet(separator string) *StringSet { |
| return &StringSet{ |
| set: make(map[string]struct{}), |
| separator: separator, |
| } |
| } |
| |
| // String satisfies flag.Value.String. |
| func (ss *StringSet) String() string { |
| keys := make([]string, 0, len(ss.set)) |
| for key := range ss.set { |
| keys = append(keys, key) |
| } |
| return fmt.Sprintf("%v", sort.StringSlice(keys)) |
| } |
| |
| // Set satisfies flag.Value.Set. |
| func (ss *StringSet) Set(s string) error { |
| list := strings.Split(s, ss.separator) |
| for _, v := range list { |
| trimmed := strings.TrimSpace(v) |
| if trimmed == "" { |
| continue |
| } |
| ss.set[trimmed] = struct{}{} |
| } |
| return nil |
| } |
| |
| // Contains returns whether the StringSet contains the provided element or not. |
| func (ss *StringSet) Contains(s string) bool { |
| _, contains := ss.set[s] |
| return contains |
| } |
| |
| // StringMapList satisfies the flag.Value interface. It constructs a string map |
| // by parsing the flag string value using the provided list and map separators. |
| type StringMapList struct { |
| mapping map[string]string |
| listSeparator string |
| mapSeparator string |
| } |
| |
| // NewStringMapList constructs a new StringMapList with the given separators. |
| func NewStringMapList(listSeparator, mapSeparator string) *StringMapList { |
| return &StringMapList{ |
| mapping: make(map[string]string), |
| listSeparator: listSeparator, |
| mapSeparator: mapSeparator, |
| } |
| } |
| |
| // String satisfies flag.Value.String. |
| func (sml *StringMapList) String() string { |
| return fmt.Sprintf("%v", sml.mapping) |
| } |
| |
| // Set satisfies flag.Value.Set. |
| func (sml *StringMapList) Set(s string) error { |
| list := strings.Split(s, sml.listSeparator) |
| for _, v := range list { |
| trimmed := strings.TrimSpace(v) |
| if trimmed == "" { |
| continue |
| } |
| mapList := strings.SplitN(trimmed, sml.mapSeparator, 2) |
| if len(mapList) < 2 { |
| return fmt.Errorf( |
| "%q is not a valid map using %q as a separator", |
| trimmed, sml.mapSeparator, |
| ) |
| } |
| key := mapList[0] |
| if _, exists := sml.mapping[key]; exists { |
| return fmt.Errorf("key %q already set", key) |
| } |
| val := mapList[1] |
| sml.mapping[key] = val |
| } |
| return nil |
| } |
| |
| // Get returns the value for the given key. |
| func (sml *StringMapList) Get(key string) (string, bool) { |
| val, exists := sml.mapping[key] |
| return val, exists |
| } |