podman
464 строки · 8.8 Кб
1package sprig
2
3import (
4"fmt"
5"math"
6"reflect"
7"sort"
8)
9
10// Reflection is used in these functions so that slices and arrays of strings,
11// ints, and other types not implementing []interface{} can be worked with.
12// For example, this is useful if you need to work on the output of regexs.
13
14func list(v ...interface{}) []interface{} {
15return v
16}
17
18func push(list interface{}, v interface{}) []interface{} {
19l, err := mustPush(list, v)
20if err != nil {
21panic(err)
22}
23
24return l
25}
26
27func mustPush(list interface{}, v interface{}) ([]interface{}, error) {
28tp := reflect.TypeOf(list).Kind()
29switch tp {
30case reflect.Slice, reflect.Array:
31l2 := reflect.ValueOf(list)
32
33l := l2.Len()
34nl := make([]interface{}, l)
35for i := 0; i < l; i++ {
36nl[i] = l2.Index(i).Interface()
37}
38
39return append(nl, v), nil
40
41default:
42return nil, fmt.Errorf("Cannot push on type %s", tp)
43}
44}
45
46func prepend(list interface{}, v interface{}) []interface{} {
47l, err := mustPrepend(list, v)
48if err != nil {
49panic(err)
50}
51
52return l
53}
54
55func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) {
56//return append([]interface{}{v}, list...)
57
58tp := reflect.TypeOf(list).Kind()
59switch tp {
60case reflect.Slice, reflect.Array:
61l2 := reflect.ValueOf(list)
62
63l := l2.Len()
64nl := make([]interface{}, l)
65for i := 0; i < l; i++ {
66nl[i] = l2.Index(i).Interface()
67}
68
69return append([]interface{}{v}, nl...), nil
70
71default:
72return nil, fmt.Errorf("Cannot prepend on type %s", tp)
73}
74}
75
76func chunk(size int, list interface{}) [][]interface{} {
77l, err := mustChunk(size, list)
78if err != nil {
79panic(err)
80}
81
82return l
83}
84
85func mustChunk(size int, list interface{}) ([][]interface{}, error) {
86tp := reflect.TypeOf(list).Kind()
87switch tp {
88case reflect.Slice, reflect.Array:
89l2 := reflect.ValueOf(list)
90
91l := l2.Len()
92
93cs := int(math.Floor(float64(l-1)/float64(size)) + 1)
94nl := make([][]interface{}, cs)
95
96for i := 0; i < cs; i++ {
97clen := size
98if i == cs-1 {
99clen = int(math.Floor(math.Mod(float64(l), float64(size))))
100if clen == 0 {
101clen = size
102}
103}
104
105nl[i] = make([]interface{}, clen)
106
107for j := 0; j < clen; j++ {
108ix := i*size + j
109nl[i][j] = l2.Index(ix).Interface()
110}
111}
112
113return nl, nil
114
115default:
116return nil, fmt.Errorf("Cannot chunk type %s", tp)
117}
118}
119
120func last(list interface{}) interface{} {
121l, err := mustLast(list)
122if err != nil {
123panic(err)
124}
125
126return l
127}
128
129func mustLast(list interface{}) (interface{}, error) {
130tp := reflect.TypeOf(list).Kind()
131switch tp {
132case reflect.Slice, reflect.Array:
133l2 := reflect.ValueOf(list)
134
135l := l2.Len()
136if l == 0 {
137return nil, nil
138}
139
140return l2.Index(l - 1).Interface(), nil
141default:
142return nil, fmt.Errorf("Cannot find last on type %s", tp)
143}
144}
145
146func first(list interface{}) interface{} {
147l, err := mustFirst(list)
148if err != nil {
149panic(err)
150}
151
152return l
153}
154
155func mustFirst(list interface{}) (interface{}, error) {
156tp := reflect.TypeOf(list).Kind()
157switch tp {
158case reflect.Slice, reflect.Array:
159l2 := reflect.ValueOf(list)
160
161l := l2.Len()
162if l == 0 {
163return nil, nil
164}
165
166return l2.Index(0).Interface(), nil
167default:
168return nil, fmt.Errorf("Cannot find first on type %s", tp)
169}
170}
171
172func rest(list interface{}) []interface{} {
173l, err := mustRest(list)
174if err != nil {
175panic(err)
176}
177
178return l
179}
180
181func mustRest(list interface{}) ([]interface{}, error) {
182tp := reflect.TypeOf(list).Kind()
183switch tp {
184case reflect.Slice, reflect.Array:
185l2 := reflect.ValueOf(list)
186
187l := l2.Len()
188if l == 0 {
189return nil, nil
190}
191
192nl := make([]interface{}, l-1)
193for i := 1; i < l; i++ {
194nl[i-1] = l2.Index(i).Interface()
195}
196
197return nl, nil
198default:
199return nil, fmt.Errorf("Cannot find rest on type %s", tp)
200}
201}
202
203func initial(list interface{}) []interface{} {
204l, err := mustInitial(list)
205if err != nil {
206panic(err)
207}
208
209return l
210}
211
212func mustInitial(list interface{}) ([]interface{}, error) {
213tp := reflect.TypeOf(list).Kind()
214switch tp {
215case reflect.Slice, reflect.Array:
216l2 := reflect.ValueOf(list)
217
218l := l2.Len()
219if l == 0 {
220return nil, nil
221}
222
223nl := make([]interface{}, l-1)
224for i := 0; i < l-1; i++ {
225nl[i] = l2.Index(i).Interface()
226}
227
228return nl, nil
229default:
230return nil, fmt.Errorf("Cannot find initial on type %s", tp)
231}
232}
233
234func sortAlpha(list interface{}) []string {
235k := reflect.Indirect(reflect.ValueOf(list)).Kind()
236switch k {
237case reflect.Slice, reflect.Array:
238a := strslice(list)
239s := sort.StringSlice(a)
240s.Sort()
241return s
242}
243return []string{strval(list)}
244}
245
246func reverse(v interface{}) []interface{} {
247l, err := mustReverse(v)
248if err != nil {
249panic(err)
250}
251
252return l
253}
254
255func mustReverse(v interface{}) ([]interface{}, error) {
256tp := reflect.TypeOf(v).Kind()
257switch tp {
258case reflect.Slice, reflect.Array:
259l2 := reflect.ValueOf(v)
260
261l := l2.Len()
262// We do not sort in place because the incoming array should not be altered.
263nl := make([]interface{}, l)
264for i := 0; i < l; i++ {
265nl[l-i-1] = l2.Index(i).Interface()
266}
267
268return nl, nil
269default:
270return nil, fmt.Errorf("Cannot find reverse on type %s", tp)
271}
272}
273
274func compact(list interface{}) []interface{} {
275l, err := mustCompact(list)
276if err != nil {
277panic(err)
278}
279
280return l
281}
282
283func mustCompact(list interface{}) ([]interface{}, error) {
284tp := reflect.TypeOf(list).Kind()
285switch tp {
286case reflect.Slice, reflect.Array:
287l2 := reflect.ValueOf(list)
288
289l := l2.Len()
290nl := []interface{}{}
291var item interface{}
292for i := 0; i < l; i++ {
293item = l2.Index(i).Interface()
294if !empty(item) {
295nl = append(nl, item)
296}
297}
298
299return nl, nil
300default:
301return nil, fmt.Errorf("Cannot compact on type %s", tp)
302}
303}
304
305func uniq(list interface{}) []interface{} {
306l, err := mustUniq(list)
307if err != nil {
308panic(err)
309}
310
311return l
312}
313
314func mustUniq(list interface{}) ([]interface{}, error) {
315tp := reflect.TypeOf(list).Kind()
316switch tp {
317case reflect.Slice, reflect.Array:
318l2 := reflect.ValueOf(list)
319
320l := l2.Len()
321dest := []interface{}{}
322var item interface{}
323for i := 0; i < l; i++ {
324item = l2.Index(i).Interface()
325if !inList(dest, item) {
326dest = append(dest, item)
327}
328}
329
330return dest, nil
331default:
332return nil, fmt.Errorf("Cannot find uniq on type %s", tp)
333}
334}
335
336func inList(haystack []interface{}, needle interface{}) bool {
337for _, h := range haystack {
338if reflect.DeepEqual(needle, h) {
339return true
340}
341}
342return false
343}
344
345func without(list interface{}, omit ...interface{}) []interface{} {
346l, err := mustWithout(list, omit...)
347if err != nil {
348panic(err)
349}
350
351return l
352}
353
354func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) {
355tp := reflect.TypeOf(list).Kind()
356switch tp {
357case reflect.Slice, reflect.Array:
358l2 := reflect.ValueOf(list)
359
360l := l2.Len()
361res := []interface{}{}
362var item interface{}
363for i := 0; i < l; i++ {
364item = l2.Index(i).Interface()
365if !inList(omit, item) {
366res = append(res, item)
367}
368}
369
370return res, nil
371default:
372return nil, fmt.Errorf("Cannot find without on type %s", tp)
373}
374}
375
376func has(needle interface{}, haystack interface{}) bool {
377l, err := mustHas(needle, haystack)
378if err != nil {
379panic(err)
380}
381
382return l
383}
384
385func mustHas(needle interface{}, haystack interface{}) (bool, error) {
386if haystack == nil {
387return false, nil
388}
389tp := reflect.TypeOf(haystack).Kind()
390switch tp {
391case reflect.Slice, reflect.Array:
392l2 := reflect.ValueOf(haystack)
393var item interface{}
394l := l2.Len()
395for i := 0; i < l; i++ {
396item = l2.Index(i).Interface()
397if reflect.DeepEqual(needle, item) {
398return true, nil
399}
400}
401
402return false, nil
403default:
404return false, fmt.Errorf("Cannot find has on type %s", tp)
405}
406}
407
408// $list := [1, 2, 3, 4, 5]
409// slice $list -> list[0:5] = list[:]
410// slice $list 0 3 -> list[0:3] = list[:3]
411// slice $list 3 5 -> list[3:5]
412// slice $list 3 -> list[3:5] = list[3:]
413func slice(list interface{}, indices ...interface{}) interface{} {
414l, err := mustSlice(list, indices...)
415if err != nil {
416panic(err)
417}
418
419return l
420}
421
422func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) {
423tp := reflect.TypeOf(list).Kind()
424switch tp {
425case reflect.Slice, reflect.Array:
426l2 := reflect.ValueOf(list)
427
428l := l2.Len()
429if l == 0 {
430return nil, nil
431}
432
433var start, end int
434if len(indices) > 0 {
435start = toInt(indices[0])
436}
437if len(indices) < 2 {
438end = l
439} else {
440end = toInt(indices[1])
441}
442
443return l2.Slice(start, end).Interface(), nil
444default:
445return nil, fmt.Errorf("list should be type of slice or array but %s", tp)
446}
447}
448
449func concat(lists ...interface{}) interface{} {
450var res []interface{}
451for _, list := range lists {
452tp := reflect.TypeOf(list).Kind()
453switch tp {
454case reflect.Slice, reflect.Array:
455l2 := reflect.ValueOf(list)
456for i := 0; i < l2.Len(); i++ {
457res = append(res, l2.Index(i).Interface())
458}
459default:
460panic(fmt.Sprintf("Cannot concat type %s as list", tp))
461}
462}
463return res
464}
465