Matteo Scandolo | a428586 | 2020-12-01 18:10:10 -0800 | [diff] [blame^] | 1 | package pflag |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "net" |
| 6 | "strconv" |
| 7 | ) |
| 8 | |
| 9 | // -- net.IPMask value |
| 10 | type ipMaskValue net.IPMask |
| 11 | |
| 12 | func newIPMaskValue(val net.IPMask, p *net.IPMask) *ipMaskValue { |
| 13 | *p = val |
| 14 | return (*ipMaskValue)(p) |
| 15 | } |
| 16 | |
| 17 | func (i *ipMaskValue) String() string { return net.IPMask(*i).String() } |
| 18 | func (i *ipMaskValue) Set(s string) error { |
| 19 | ip := ParseIPv4Mask(s) |
| 20 | if ip == nil { |
| 21 | return fmt.Errorf("failed to parse IP mask: %q", s) |
| 22 | } |
| 23 | *i = ipMaskValue(ip) |
| 24 | return nil |
| 25 | } |
| 26 | |
| 27 | func (i *ipMaskValue) Type() string { |
| 28 | return "ipMask" |
| 29 | } |
| 30 | |
| 31 | // ParseIPv4Mask written in IP form (e.g. 255.255.255.0). |
| 32 | // This function should really belong to the net package. |
| 33 | func ParseIPv4Mask(s string) net.IPMask { |
| 34 | mask := net.ParseIP(s) |
| 35 | if mask == nil { |
| 36 | if len(s) != 8 { |
| 37 | return nil |
| 38 | } |
| 39 | // net.IPMask.String() actually outputs things like ffffff00 |
| 40 | // so write a horrible parser for that as well :-( |
| 41 | m := []int{} |
| 42 | for i := 0; i < 4; i++ { |
| 43 | b := "0x" + s[2*i:2*i+2] |
| 44 | d, err := strconv.ParseInt(b, 0, 0) |
| 45 | if err != nil { |
| 46 | return nil |
| 47 | } |
| 48 | m = append(m, int(d)) |
| 49 | } |
| 50 | s := fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3]) |
| 51 | mask = net.ParseIP(s) |
| 52 | if mask == nil { |
| 53 | return nil |
| 54 | } |
| 55 | } |
| 56 | return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15]) |
| 57 | } |
| 58 | |
| 59 | func parseIPv4Mask(sval string) (interface{}, error) { |
| 60 | mask := ParseIPv4Mask(sval) |
| 61 | if mask == nil { |
| 62 | return nil, fmt.Errorf("unable to parse %s as net.IPMask", sval) |
| 63 | } |
| 64 | return mask, nil |
| 65 | } |
| 66 | |
| 67 | // GetIPv4Mask return the net.IPv4Mask value of a flag with the given name |
| 68 | func (f *FlagSet) GetIPv4Mask(name string) (net.IPMask, error) { |
| 69 | val, err := f.getFlagType(name, "ipMask", parseIPv4Mask) |
| 70 | if err != nil { |
| 71 | return nil, err |
| 72 | } |
| 73 | return val.(net.IPMask), nil |
| 74 | } |
| 75 | |
| 76 | // IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string. |
| 77 | // The argument p points to an net.IPMask variable in which to store the value of the flag. |
| 78 | func (f *FlagSet) IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) { |
| 79 | f.VarP(newIPMaskValue(value, p), name, "", usage) |
| 80 | } |
| 81 | |
| 82 | // IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash. |
| 83 | func (f *FlagSet) IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) { |
| 84 | f.VarP(newIPMaskValue(value, p), name, shorthand, usage) |
| 85 | } |
| 86 | |
| 87 | // IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string. |
| 88 | // The argument p points to an net.IPMask variable in which to store the value of the flag. |
| 89 | func IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) { |
| 90 | CommandLine.VarP(newIPMaskValue(value, p), name, "", usage) |
| 91 | } |
| 92 | |
| 93 | // IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash. |
| 94 | func IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) { |
| 95 | CommandLine.VarP(newIPMaskValue(value, p), name, shorthand, usage) |
| 96 | } |
| 97 | |
| 98 | // IPMask defines an net.IPMask flag with specified name, default value, and usage string. |
| 99 | // The return value is the address of an net.IPMask variable that stores the value of the flag. |
| 100 | func (f *FlagSet) IPMask(name string, value net.IPMask, usage string) *net.IPMask { |
| 101 | p := new(net.IPMask) |
| 102 | f.IPMaskVarP(p, name, "", value, usage) |
| 103 | return p |
| 104 | } |
| 105 | |
| 106 | // IPMaskP is like IPMask, but accepts a shorthand letter that can be used after a single dash. |
| 107 | func (f *FlagSet) IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask { |
| 108 | p := new(net.IPMask) |
| 109 | f.IPMaskVarP(p, name, shorthand, value, usage) |
| 110 | return p |
| 111 | } |
| 112 | |
| 113 | // IPMask defines an net.IPMask flag with specified name, default value, and usage string. |
| 114 | // The return value is the address of an net.IPMask variable that stores the value of the flag. |
| 115 | func IPMask(name string, value net.IPMask, usage string) *net.IPMask { |
| 116 | return CommandLine.IPMaskP(name, "", value, usage) |
| 117 | } |
| 118 | |
| 119 | // IPMaskP is like IP, but accepts a shorthand letter that can be used after a single dash. |
| 120 | func IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask { |
| 121 | return CommandLine.IPMaskP(name, shorthand, value, usage) |
| 122 | } |