podman
464 строки · 8.8 Кб
1package sprig2
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 v16}
17
18func push(list interface{}, v interface{}) []interface{} {19l, err := mustPush(list, v)20if err != nil {21panic(err)22}23
24return l25}
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), nil40
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 l53}
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...), nil70
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 l83}
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 := size98if i == cs-1 {99clen = int(math.Floor(math.Mod(float64(l), float64(size))))100if clen == 0 {101clen = size102}103}104
105nl[i] = make([]interface{}, clen)106
107for j := 0; j < clen; j++ {108ix := i*size + j109nl[i][j] = l2.Index(ix).Interface()110}111}112
113return nl, nil114
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 l127}
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, nil138}139
140return l2.Index(l - 1).Interface(), nil141default: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 l153}
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, nil164}165
166return l2.Index(0).Interface(), nil167default: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 l179}
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, nil190}191
192nl := make([]interface{}, l-1)193for i := 1; i < l; i++ {194nl[i-1] = l2.Index(i).Interface()195}196
197return nl, nil198default: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 l210}
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, nil221}222
223nl := make([]interface{}, l-1)224for i := 0; i < l-1; i++ {225nl[i] = l2.Index(i).Interface()226}227
228return nl, nil229default: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 s242}243return []string{strval(list)}244}
245
246func reverse(v interface{}) []interface{} {247l, err := mustReverse(v)248if err != nil {249panic(err)250}251
252return l253}
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, nil269default: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 l281}
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, nil300default: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 l312}
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, nil331default: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 true340}341}342return false343}
344
345func without(list interface{}, omit ...interface{}) []interface{} {346l, err := mustWithout(list, omit...)347if err != nil {348panic(err)349}350
351return l352}
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, nil371default: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 l383}
384
385func mustHas(needle interface{}, haystack interface{}) (bool, error) {386if haystack == nil {387return false, nil388}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, nil399}400}401
402return false, nil403default: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 l420}
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, nil431}432
433var start, end int434if len(indices) > 0 {435start = toInt(indices[0])436}437if len(indices) < 2 {438end = l439} else {440end = toInt(indices[1])441}442
443return l2.Slice(start, end).Interface(), nil444default: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 res464}
465