ip_slice.go (5412B)
1 package pflag 2 3 import ( 4 "fmt" 5 "io" 6 "net" 7 "strings" 8 ) 9 10 // -- ipSlice Value 11 type ipSliceValue struct { 12 value *[]net.IP 13 changed bool 14 } 15 16 func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue { 17 ipsv := new(ipSliceValue) 18 ipsv.value = p 19 *ipsv.value = val 20 return ipsv 21 } 22 23 // Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag. 24 // If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended. 25 func (s *ipSliceValue) Set(val string) error { 26 27 // remove all quote characters 28 rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") 29 30 // read flag arguments with CSV parser 31 ipStrSlice, err := readAsCSV(rmQuote.Replace(val)) 32 if err != nil && err != io.EOF { 33 return err 34 } 35 36 // parse ip values into slice 37 out := make([]net.IP, 0, len(ipStrSlice)) 38 for _, ipStr := range ipStrSlice { 39 ip := net.ParseIP(strings.TrimSpace(ipStr)) 40 if ip == nil { 41 return fmt.Errorf("invalid string being converted to IP address: %s", ipStr) 42 } 43 out = append(out, ip) 44 } 45 46 if !s.changed { 47 *s.value = out 48 } else { 49 *s.value = append(*s.value, out...) 50 } 51 52 s.changed = true 53 54 return nil 55 } 56 57 // Type returns a string that uniquely represents this flag's type. 58 func (s *ipSliceValue) Type() string { 59 return "ipSlice" 60 } 61 62 // String defines a "native" format for this net.IP slice flag value. 63 func (s *ipSliceValue) String() string { 64 65 ipStrSlice := make([]string, len(*s.value)) 66 for i, ip := range *s.value { 67 ipStrSlice[i] = ip.String() 68 } 69 70 out, _ := writeAsCSV(ipStrSlice) 71 72 return "[" + out + "]" 73 } 74 75 func (s *ipSliceValue) fromString(val string) (net.IP, error) { 76 return net.ParseIP(strings.TrimSpace(val)), nil 77 } 78 79 func (s *ipSliceValue) toString(val net.IP) string { 80 return val.String() 81 } 82 83 func (s *ipSliceValue) Append(val string) error { 84 i, err := s.fromString(val) 85 if err != nil { 86 return err 87 } 88 *s.value = append(*s.value, i) 89 return nil 90 } 91 92 func (s *ipSliceValue) Replace(val []string) error { 93 out := make([]net.IP, len(val)) 94 for i, d := range val { 95 var err error 96 out[i], err = s.fromString(d) 97 if err != nil { 98 return err 99 } 100 } 101 *s.value = out 102 return nil 103 } 104 105 func (s *ipSliceValue) GetSlice() []string { 106 out := make([]string, len(*s.value)) 107 for i, d := range *s.value { 108 out[i] = s.toString(d) 109 } 110 return out 111 } 112 113 func ipSliceConv(val string) (interface{}, error) { 114 val = strings.Trim(val, "[]") 115 // Empty string would cause a slice with one (empty) entry 116 if len(val) == 0 { 117 return []net.IP{}, nil 118 } 119 ss := strings.Split(val, ",") 120 out := make([]net.IP, len(ss)) 121 for i, sval := range ss { 122 ip := net.ParseIP(strings.TrimSpace(sval)) 123 if ip == nil { 124 return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) 125 } 126 out[i] = ip 127 } 128 return out, nil 129 } 130 131 // GetIPSlice returns the []net.IP value of a flag with the given name 132 func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) { 133 val, err := f.getFlagType(name, "ipSlice", ipSliceConv) 134 if err != nil { 135 return []net.IP{}, err 136 } 137 return val.([]net.IP), nil 138 } 139 140 // IPSliceVar defines a ipSlice flag with specified name, default value, and usage string. 141 // The argument p points to a []net.IP variable in which to store the value of the flag. 142 func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { 143 f.VarP(newIPSliceValue(value, p), name, "", usage) 144 } 145 146 // IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. 147 func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { 148 f.VarP(newIPSliceValue(value, p), name, shorthand, usage) 149 } 150 151 // IPSliceVar defines a []net.IP flag with specified name, default value, and usage string. 152 // The argument p points to a []net.IP variable in which to store the value of the flag. 153 func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { 154 CommandLine.VarP(newIPSliceValue(value, p), name, "", usage) 155 } 156 157 // IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. 158 func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { 159 CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage) 160 } 161 162 // IPSlice defines a []net.IP flag with specified name, default value, and usage string. 163 // The return value is the address of a []net.IP variable that stores the value of that flag. 164 func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP { 165 p := []net.IP{} 166 f.IPSliceVarP(&p, name, "", value, usage) 167 return &p 168 } 169 170 // IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. 171 func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { 172 p := []net.IP{} 173 f.IPSliceVarP(&p, name, shorthand, value, usage) 174 return &p 175 } 176 177 // IPSlice defines a []net.IP flag with specified name, default value, and usage string. 178 // The return value is the address of a []net.IP variable that stores the value of the flag. 179 func IPSlice(name string, value []net.IP, usage string) *[]net.IP { 180 return CommandLine.IPSliceP(name, "", value, usage) 181 } 182 183 // IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. 184 func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { 185 return CommandLine.IPSliceP(name, shorthand, value, usage) 186 }