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
15package types
16
17import (
18	"fmt"
19	"sort"
20	"strings"
21)
22
23// URLsMap is a map from a name to its URLs.
24type 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
29func 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.
45func 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.
58func (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.
71func (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.
83func (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.
88func 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}
108