ip_slice.go 5.3 KB

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