github.com/ali-iotechsys/cli@v20.10.0+incompatible/cli/command/swarm/ipnet_slice.go (about)

     1  package swarm
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/csv"
     6  	"fmt"
     7  	"io"
     8  	"net"
     9  	"strings"
    10  )
    11  
    12  // -- ipNetSlice Value
    13  type ipNetSliceValue struct {
    14  	value   *[]net.IPNet
    15  	changed bool
    16  }
    17  
    18  func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue {
    19  	ipnsv := new(ipNetSliceValue)
    20  	ipnsv.value = p
    21  	*ipnsv.value = val
    22  	return ipnsv
    23  }
    24  
    25  // Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag.
    26  // If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended.
    27  func (s *ipNetSliceValue) Set(val string) error {
    28  
    29  	// remove all quote characters
    30  	rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
    31  
    32  	// read flag arguments with CSV parser
    33  	ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val))
    34  	if err != nil && err != io.EOF {
    35  		return err
    36  	}
    37  
    38  	// parse ip values into slice
    39  	out := make([]net.IPNet, 0, len(ipNetStrSlice))
    40  	for _, ipNetStr := range ipNetStrSlice {
    41  		_, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr))
    42  		if err != nil {
    43  			return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr)
    44  		}
    45  		out = append(out, *n)
    46  	}
    47  
    48  	if !s.changed {
    49  		*s.value = out
    50  	} else {
    51  		*s.value = append(*s.value, out...)
    52  	}
    53  
    54  	s.changed = true
    55  
    56  	return nil
    57  }
    58  
    59  // Type returns a string that uniquely represents this flag's type.
    60  func (s *ipNetSliceValue) Type() string {
    61  	return "ipNetSlice"
    62  }
    63  
    64  // String defines a "native" format for this net.IPNet slice flag value.
    65  func (s *ipNetSliceValue) String() string {
    66  
    67  	ipNetStrSlice := make([]string, len(*s.value))
    68  	for i, n := range *s.value {
    69  		ipNetStrSlice[i] = n.String()
    70  	}
    71  
    72  	out, _ := writeAsCSV(ipNetStrSlice)
    73  	return "[" + out + "]"
    74  }
    75  
    76  func readAsCSV(val string) ([]string, error) {
    77  	if val == "" {
    78  		return []string{}, nil
    79  	}
    80  	stringReader := strings.NewReader(val)
    81  	csvReader := csv.NewReader(stringReader)
    82  	return csvReader.Read()
    83  }
    84  
    85  func writeAsCSV(vals []string) (string, error) {
    86  	b := &bytes.Buffer{}
    87  	w := csv.NewWriter(b)
    88  	err := w.Write(vals)
    89  	if err != nil {
    90  		return "", err
    91  	}
    92  	w.Flush()
    93  	return strings.TrimSuffix(b.String(), "\n"), nil
    94  }