master
go 200 lines 3.51 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package l2topology
4
5 import (
6 "maps"
7 "net/netip"
8 "sort"
9 "strings"
10 )
11
12 func cloneAnyMap(in map[string]any) map[string]any {
13 if len(in) == 0 {
14 return nil
15 }
16 out := make(map[string]any, len(in))
17 maps.Copy(out, in)
18 return out
19 }
20
21 func cloneStringMap(in map[string]string) map[string]string {
22 if len(in) == 0 {
23 return nil
24 }
25 out := make(map[string]string, len(in))
26 maps.Copy(out, in)
27 return out
28 }
29
30 func addressStrings(addresses []netip.Addr) []string {
31 if len(addresses) == 0 {
32 return nil
33 }
34 out := make([]string, 0, len(addresses))
35 for _, addr := range addresses {
36 if !addr.IsValid() {
37 continue
38 }
39 out = append(out, addr.Unmap().String())
40 }
41 out = uniqueTopologyStrings(out)
42 if len(out) == 0 {
43 return nil
44 }
45 return out
46 }
47
48 func firstAddress(addresses []netip.Addr) string {
49 values := addressStrings(addresses)
50 if len(values) == 0 {
51 return ""
52 }
53 return values[0]
54 }
55
56 func uniqueTopologyStrings(values []string) []string {
57 if len(values) == 0 {
58 return nil
59 }
60 seen := make(map[string]struct{}, len(values))
61 out := make([]string, 0, len(values))
62 for _, value := range values {
63 value = strings.TrimSpace(value)
64 if value == "" {
65 continue
66 }
67 if _, ok := seen[value]; ok {
68 continue
69 }
70 seen[value] = struct{}{}
71 out = append(out, value)
72 }
73 sort.Strings(out)
74 if len(out) == 0 {
75 return nil
76 }
77 return out
78 }
79
80 func sortedEndpointIPs(in map[string]netip.Addr) []string {
81 if len(in) == 0 {
82 return nil
83 }
84 keys := make([]string, 0, len(in))
85 for key := range in {
86 keys = append(keys, key)
87 }
88 sort.Strings(keys)
89
90 out := make([]string, 0, len(keys))
91 for _, key := range keys {
92 addr, ok := in[key]
93 if !ok || !addr.IsValid() {
94 continue
95 }
96 out = append(out, addr.Unmap().String())
97 }
98 out = uniqueTopologyStrings(out)
99 if len(out) == 0 {
100 return nil
101 }
102 return out
103 }
104
105 func sortedTopologySet(in map[string]struct{}) []string {
106 if len(in) == 0 {
107 return nil
108 }
109 out := make([]string, 0, len(in))
110 for value := range in {
111 value = strings.TrimSpace(value)
112 if value == "" {
113 continue
114 }
115 out = append(out, value)
116 }
117 sort.Strings(out)
118 if len(out) == 0 {
119 return nil
120 }
121 return out
122 }
123
124 func csvToSet(value string) []string {
125 value = strings.TrimSpace(value)
126 if value == "" {
127 return nil
128 }
129 parts := strings.Split(value, ",")
130 out := make([]string, 0, len(parts))
131 for _, part := range parts {
132 part = strings.TrimSpace(part)
133 if part == "" {
134 continue
135 }
136 out = append(out, part)
137 }
138 if len(out) == 0 {
139 return nil
140 }
141 return out
142 }
143
144 func labelsCSVToSlice(labels map[string]string, key string) []string {
145 if len(labels) == 0 {
146 return nil
147 }
148 return csvToSet(labels[key])
149 }
150
151 func pruneTopologyAttributes(attrs map[string]any) map[string]any {
152 for key, value := range attrs {
153 switch typed := value.(type) {
154 case string:
155 if strings.TrimSpace(typed) == "" {
156 delete(attrs, key)
157 }
158 case []string:
159 if len(typed) == 0 {
160 delete(attrs, key)
161 }
162 case map[string]string:
163 if len(typed) == 0 {
164 delete(attrs, key)
165 }
166 case map[string]any:
167 if len(typed) == 0 {
168 delete(attrs, key)
169 }
170 case int:
171 if typed == 0 {
172 delete(attrs, key)
173 }
174 case nil:
175 delete(attrs, key)
176 }
177 }
178 if len(attrs) == 0 {
179 return nil
180 }
181 return attrs
182 }
183
184 func mapStringStringToAny(in map[string]string) map[string]any {
185 if len(in) == 0 {
186 return nil
187 }
188 out := make(map[string]any, len(in))
189 for key, value := range in {
190 value = strings.TrimSpace(value)
191 if value == "" {
192 continue
193 }
194 out[key] = value
195 }
196 if len(out) == 0 {
197 return nil
198 }
199 return out
200 }