ipnet_slice.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package pflag
  2. import (
  3. "fmt"
  4. "io"
  5. "net"
  6. "strings"
  7. )
  8. // -- ipNetSlice Value
  9. type ipNetSliceValue struct {
  10. value *[]net.IPNet
  11. changed bool
  12. }
  13. func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue {
  14. ipnsv := new(ipNetSliceValue)
  15. ipnsv.value = p
  16. *ipnsv.value = val
  17. return ipnsv
  18. }
  19. // Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag.
  20. // If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended.
  21. func (s *ipNetSliceValue) Set(val string) error {
  22. // remove all quote characters
  23. rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
  24. // read flag arguments with CSV parser
  25. ipNetStrSlice, 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.IPNet, 0, len(ipNetStrSlice))
  31. for _, ipNetStr := range ipNetStrSlice {
  32. _, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr))
  33. if err != nil {
  34. return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr)
  35. }
  36. out = append(out, *n)
  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 *ipNetSliceValue) Type() string {
  48. return "ipNetSlice"
  49. }
  50. // String defines a "native" format for this net.IPNet slice flag value.
  51. func (s *ipNetSliceValue) String() string {
  52. ipNetStrSlice := make([]string, len(*s.value))
  53. for i, n := range *s.value {
  54. ipNetStrSlice[i] = n.String()
  55. }
  56. out, _ := writeAsCSV(ipNetStrSlice)
  57. return "[" + out + "]"
  58. }
  59. func ipNetSliceConv(val string) (interface{}, error) {
  60. val = strings.Trim(val, "[]")
  61. // Emtpy string would cause a slice with one (empty) entry
  62. if len(val) == 0 {
  63. return []net.IPNet{}, nil
  64. }
  65. ss := strings.Split(val, ",")
  66. out := make([]net.IPNet, len(ss))
  67. for i, sval := range ss {
  68. _, n, err := net.ParseCIDR(strings.TrimSpace(sval))
  69. if err != nil {
  70. return nil, fmt.Errorf("invalid string being converted to CIDR: %s", sval)
  71. }
  72. out[i] = *n
  73. }
  74. return out, nil
  75. }
  76. // GetIPNetSlice returns the []net.IPNet value of a flag with the given name
  77. func (f *FlagSet) GetIPNetSlice(name string) ([]net.IPNet, error) {
  78. val, err := f.getFlagType(name, "ipNetSlice", ipNetSliceConv)
  79. if err != nil {
  80. return []net.IPNet{}, err
  81. }
  82. return val.([]net.IPNet), nil
  83. }
  84. // IPNetSliceVar defines a ipNetSlice flag with specified name, default value, and usage string.
  85. // The argument p points to a []net.IPNet variable in which to store the value of the flag.
  86. func (f *FlagSet) IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
  87. f.VarP(newIPNetSliceValue(value, p), name, "", usage)
  88. }
  89. // IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
  90. func (f *FlagSet) IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
  91. f.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
  92. }
  93. // IPNetSliceVar defines a []net.IPNet flag with specified name, default value, and usage string.
  94. // The argument p points to a []net.IPNet variable in which to store the value of the flag.
  95. func IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
  96. CommandLine.VarP(newIPNetSliceValue(value, p), name, "", usage)
  97. }
  98. // IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
  99. func IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
  100. CommandLine.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
  101. }
  102. // IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
  103. // The return value is the address of a []net.IPNet variable that stores the value of that flag.
  104. func (f *FlagSet) IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
  105. p := []net.IPNet{}
  106. f.IPNetSliceVarP(&p, name, "", value, usage)
  107. return &p
  108. }
  109. // IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
  110. func (f *FlagSet) IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
  111. p := []net.IPNet{}
  112. f.IPNetSliceVarP(&p, name, shorthand, value, usage)
  113. return &p
  114. }
  115. // IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
  116. // The return value is the address of a []net.IP variable that stores the value of the flag.
  117. func IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
  118. return CommandLine.IPNetSliceP(name, "", value, usage)
  119. }
  120. // IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
  121. func IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
  122. return CommandLine.IPNetSliceP(name, shorthand, value, usage)
  123. }