1
15
16 package rule
17
18 import (
19 "sort"
20 "strings"
21
22 bzl "github.com/bazelbuild/buildtools/build"
23 )
24
25
26
27
28
29 type PlatformConstraint struct {
30 Platform
31 ConstraintPrefix string
32 }
33
34 func (p PlatformConstraint) String() string {
35 pStr := p.Platform.String()
36 if pStr == "" {
37 return ""
38 }
39 return p.ConstraintPrefix + pStr
40 }
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 type PlatformStrings struct {
56
57 Generic []string
58
59
60 OS map[string][]string
61
62
63
64 Arch map[string][]string
65
66
67
68 Platform map[PlatformConstraint][]string
69 }
70
71
72 func (ps *PlatformStrings) HasExt(ext string) bool {
73 return ps.firstExtFile(ext) != ""
74 }
75
76 func (ps *PlatformStrings) IsEmpty() bool {
77 return len(ps.Generic) == 0 && len(ps.OS) == 0 && len(ps.Arch) == 0 && len(ps.Platform) == 0
78 }
79
80
81 func (ps *PlatformStrings) Flat() []string {
82 unique := make(map[string]struct{})
83 for _, s := range ps.Generic {
84 unique[s] = struct{}{}
85 }
86 for _, ss := range ps.OS {
87 for _, s := range ss {
88 unique[s] = struct{}{}
89 }
90 }
91 for _, ss := range ps.Arch {
92 for _, s := range ss {
93 unique[s] = struct{}{}
94 }
95 }
96 for _, ss := range ps.Platform {
97 for _, s := range ss {
98 unique[s] = struct{}{}
99 }
100 }
101 flat := make([]string, 0, len(unique))
102 for s := range unique {
103 flat = append(flat, s)
104 }
105 sort.Strings(flat)
106 return flat
107 }
108
109 func (ps *PlatformStrings) firstExtFile(ext string) string {
110 for _, f := range ps.Generic {
111 if strings.HasSuffix(f, ext) {
112 return f
113 }
114 }
115 for _, fs := range ps.OS {
116 for _, f := range fs {
117 if strings.HasSuffix(f, ext) {
118 return f
119 }
120 }
121 }
122 for _, fs := range ps.Arch {
123 for _, f := range fs {
124 if strings.HasSuffix(f, ext) {
125 return f
126 }
127 }
128 }
129 for _, fs := range ps.Platform {
130 for _, f := range fs {
131 if strings.HasSuffix(f, ext) {
132 return f
133 }
134 }
135 }
136 return ""
137 }
138
139
140
141
142 func (ps *PlatformStrings) Map(f func(s string) (string, error)) (PlatformStrings, []error) {
143 var errors []error
144 mapSlice := func(ss []string) ([]string, error) {
145 rs := make([]string, 0, len(ss))
146 for _, s := range ss {
147 if r, err := f(s); err != nil {
148 errors = append(errors, err)
149 } else if r != "" {
150 rs = append(rs, r)
151 }
152 }
153 return rs, nil
154 }
155 result, _ := ps.MapSlice(mapSlice)
156 return result, errors
157 }
158
159
160
161 func (ps *PlatformStrings) MapSlice(f func([]string) ([]string, error)) (PlatformStrings, []error) {
162 var errors []error
163
164 mapSlice := func(ss []string) []string {
165 rs, err := f(ss)
166 if err != nil {
167 errors = append(errors, err)
168 return nil
169 }
170 return rs
171 }
172
173 mapStringMap := func(m map[string][]string) map[string][]string {
174 if m == nil {
175 return nil
176 }
177 rm := make(map[string][]string)
178 for k, ss := range m {
179 ss = mapSlice(ss)
180 if len(ss) > 0 {
181 rm[k] = ss
182 }
183 }
184 if len(rm) == 0 {
185 return nil
186 }
187 return rm
188 }
189
190 mapPlatformMap := func(m map[PlatformConstraint][]string) map[PlatformConstraint][]string {
191 if m == nil {
192 return nil
193 }
194 rm := make(map[PlatformConstraint][]string)
195 for k, ss := range m {
196 ss = mapSlice(ss)
197 if len(ss) > 0 {
198 rm[k] = ss
199 }
200 }
201 if len(rm) == 0 {
202 return nil
203 }
204 return rm
205 }
206
207 result := PlatformStrings{
208 Generic: mapSlice(ps.Generic),
209 OS: mapStringMap(ps.OS),
210 Arch: mapStringMap(ps.Arch),
211 Platform: mapPlatformMap(ps.Platform),
212 }
213 return result, errors
214 }
215
216 func (ps PlatformStrings) BzlExpr() bzl.Expr {
217 var pieces []bzl.Expr
218 if len(ps.Generic) > 0 {
219 pieces = append(pieces, ExprFromValue(ps.Generic))
220 }
221 if len(ps.OS) > 0 {
222 pieces = append(pieces, platformStringsOSArchDictExpr(ps.OS))
223 }
224 if len(ps.Arch) > 0 {
225 pieces = append(pieces, platformStringsOSArchDictExpr(ps.Arch))
226 }
227 if len(ps.Platform) > 0 {
228 pieces = append(pieces, platformStringsPlatformDictExpr(ps.Platform))
229 }
230 if len(pieces) == 0 {
231 return &bzl.ListExpr{}
232 } else if len(pieces) == 1 {
233 return pieces[0]
234 } else {
235 e := pieces[0]
236 if list, ok := e.(*bzl.ListExpr); ok {
237 list.ForceMultiLine = true
238 }
239 for _, piece := range pieces[1:] {
240 e = &bzl.BinaryExpr{X: e, Y: piece, Op: "+"}
241 }
242 return e
243 }
244 }
245
246 func platformStringsOSArchDictExpr(m map[string][]string) bzl.Expr {
247 s := make(SelectStringListValue)
248 for key, value := range m {
249 s[key] = value
250 }
251 s["//conditions:default"] = nil
252 return s.BzlExpr()
253 }
254
255 func platformStringsPlatformDictExpr(m map[PlatformConstraint][]string) bzl.Expr {
256 s := make(SelectStringListValue)
257 for key, value := range m {
258 s[key.String()] = value
259 }
260 s["//conditions:default"] = nil
261 return s.BzlExpr()
262 }
263
View as plain text