go.etcd.io/etcd@v3.3.27+incompatible/pkg/types/urlsmap.go (about)

     1  // Copyright 2015 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package types
    16  
    17  import (
    18  	"fmt"
    19  	"sort"
    20  	"strings"
    21  )
    22  
    23  // URLsMap is a map from a name to its URLs.
    24  type URLsMap map[string]URLs
    25  
    26  // NewURLsMap returns a URLsMap instantiated from the given string,
    27  // which consists of discovery-formatted names-to-URLs, like:
    28  // mach0=http://1.1.1.1:2380,mach0=http://2.2.2.2::2380,mach1=http://3.3.3.3:2380,mach2=http://4.4.4.4:2380
    29  func NewURLsMap(s string) (URLsMap, error) {
    30  	m := parse(s)
    31  
    32  	cl := URLsMap{}
    33  	for name, urls := range m {
    34  		us, err := NewURLs(urls)
    35  		if err != nil {
    36  			return nil, err
    37  		}
    38  		cl[name] = us
    39  	}
    40  	return cl, nil
    41  }
    42  
    43  // NewURLsMapFromStringMap takes a map of strings and returns a URLsMap. The
    44  // string values in the map can be multiple values separated by the sep string.
    45  func NewURLsMapFromStringMap(m map[string]string, sep string) (URLsMap, error) {
    46  	var err error
    47  	um := URLsMap{}
    48  	for k, v := range m {
    49  		um[k], err = NewURLs(strings.Split(v, sep))
    50  		if err != nil {
    51  			return nil, err
    52  		}
    53  	}
    54  	return um, nil
    55  }
    56  
    57  // String turns URLsMap into discovery-formatted name-to-URLs sorted by name.
    58  func (c URLsMap) String() string {
    59  	var pairs []string
    60  	for name, urls := range c {
    61  		for _, url := range urls {
    62  			pairs = append(pairs, fmt.Sprintf("%s=%s", name, url.String()))
    63  		}
    64  	}
    65  	sort.Strings(pairs)
    66  	return strings.Join(pairs, ",")
    67  }
    68  
    69  // URLs returns a list of all URLs.
    70  // The returned list is sorted in ascending lexicographical order.
    71  func (c URLsMap) URLs() []string {
    72  	var urls []string
    73  	for _, us := range c {
    74  		for _, u := range us {
    75  			urls = append(urls, u.String())
    76  		}
    77  	}
    78  	sort.Strings(urls)
    79  	return urls
    80  }
    81  
    82  // Len returns the size of URLsMap.
    83  func (c URLsMap) Len() int {
    84  	return len(c)
    85  }
    86  
    87  // parse parses the given string and returns a map listing the values specified for each key.
    88  func parse(s string) map[string][]string {
    89  	m := make(map[string][]string)
    90  	for s != "" {
    91  		key := s
    92  		if i := strings.IndexAny(key, ","); i >= 0 {
    93  			key, s = key[:i], key[i+1:]
    94  		} else {
    95  			s = ""
    96  		}
    97  		if key == "" {
    98  			continue
    99  		}
   100  		value := ""
   101  		if i := strings.Index(key, "="); i >= 0 {
   102  			key, value = key[:i], key[i+1:]
   103  		}
   104  		m[key] = append(m[key], value)
   105  	}
   106  	return m
   107  }