File: func_index.go

package info (click to toggle)
dasel 2.8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,844 kB
  • sloc: sh: 53; python: 21; makefile: 21; xml: 20
file content (92 lines) | stat: -rw-r--r-- 2,161 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package dasel

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
)

type ErrIndexNotFound struct {
	Index int
}

func (e ErrIndexNotFound) Error() string {
	return fmt.Sprintf("index not found: %d", e.Index)
}

func (e ErrIndexNotFound) Is(other error) bool {
	o, ok := other.(*ErrIndexNotFound)
	if !ok {
		return false
	}
	if o.Index >= 0 && o.Index != e.Index {
		return false
	}
	return true
}

var IndexFunc = BasicFunction{
	name: "index",
	runFn: func(c *Context, s *Step, args []string) (Values, error) {
		if err := requireXOrMoreArgs("index", args, 1); err != nil {
			return nil, err
		}

		input := s.inputs()

		res := make(Values, 0)

		for _, val := range input {
			for _, indexStr := range args {
				isOptional := strings.HasSuffix(indexStr, "?")
				if isOptional {
					indexStr = strings.TrimSuffix(indexStr, "?")
				}

				index, err := strconv.Atoi(indexStr)
				if err != nil {
					if isOptional {
						continue
					}
					return nil, fmt.Errorf("invalid index: %w", err)
				}

				switch val.Kind() {
				case reflect.String:
					runes := []rune(val.String())
					if index < 0 || index > len(runes)-1 {
						if isOptional {
							continue
						}
						return nil, fmt.Errorf("index out of range: %w", &ErrIndexNotFound{Index: index})
					}
					res = append(res, ValueOf(string(runes[index])))
				case reflect.Slice, reflect.Array:
					if index < 0 || index > val.Len()-1 {
						if isOptional {
							continue
						}
						return nil, fmt.Errorf("index out of range: %w", &ErrIndexNotFound{Index: index})
					}
					value := val.Index(index)
					res = append(res, value)
				default:
					return nil, fmt.Errorf("cannot use index selector on non slice/array types: %w", &ErrIndexNotFound{Index: index})
				}
			}
		}

		return res, nil
	},
	alternativeSelectorFn: func(part string) *Selector {
		if part != "[]" && strings.HasPrefix(part, "[") && strings.HasSuffix(part, "]") {
			strings.Split(strings.TrimPrefix(strings.TrimSuffix(part, "]"), "["), ",")
			return &Selector{
				funcName: "index",
				funcArgs: strings.Split(strings.TrimPrefix(strings.TrimSuffix(part, "]"), "["), ","),
			}
		}
		return nil
	},
}