builtin

package
v1.15.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 3, 2023 License: MIT Imports: 11 Imported by: 16

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	Index map[string]int
	Names []string
)
View Source
var Builtins = []*ast.Function{
	{
		Name:      "all",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) bool)),
	},
	{
		Name:      "none",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) bool)),
	},
	{
		Name:      "any",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) bool)),
	},
	{
		Name:      "one",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) bool)),
	},
	{
		Name:      "filter",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) []any)),
	},
	{
		Name:      "map",
		Predicate: true,
		Types:     types(new(func([]any, func(any) any) []any)),
	},
	{
		Name:      "find",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) any)),
	},
	{
		Name:      "findIndex",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) int)),
	},
	{
		Name:      "findLast",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) any)),
	},
	{
		Name:      "findLastIndex",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) int)),
	},
	{
		Name:      "count",
		Predicate: true,
		Types:     types(new(func([]any, func(any) bool) int)),
	},
	{
		Name:      "groupBy",
		Predicate: true,
		Types:     types(new(func([]any, func(any) any) map[any][]any)),
	},
	{
		Name:      "reduce",
		Predicate: true,
		Types:     types(new(func([]any, func(any, any) any, any) any)),
	},
	{
		Name: "len",
		Fast: Len,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Array, reflect.Map, reflect.Slice, reflect.String, reflect.Interface:
				return integerType, nil
			}
			return anyType, fmt.Errorf("invalid argument for len (type %s)", args[0])
		},
	},
	{
		Name:  "type",
		Fast:  Type,
		Types: types(new(func(any) string)),
	},
	{
		Name: "abs",
		Fast: Abs,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface:
				return args[0], nil
			}
			return anyType, fmt.Errorf("invalid argument for abs (type %s)", args[0])
		},
	},
	{
		Name: "ceil",
		Fast: Ceil,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface:
				return floatType, nil
			}
			return anyType, fmt.Errorf("invalid argument for ceil (type %s)", args[0])
		},
	},
	{
		Name: "floor",
		Fast: Floor,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface:
				return floatType, nil
			}
			return anyType, fmt.Errorf("invalid argument for floor (type %s)", args[0])
		},
	},
	{
		Name: "round",
		Fast: Round,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface:
				return floatType, nil
			}
			return anyType, fmt.Errorf("invalid argument for floor (type %s)", args[0])
		},
	},
	{
		Name: "int",
		Fast: Int,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface:
				return integerType, nil
			case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
				return integerType, nil
			case reflect.String:
				return integerType, nil
			}
			return anyType, fmt.Errorf("invalid argument for int (type %s)", args[0])
		},
	},
	{
		Name: "float",
		Fast: Float,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface:
				return floatType, nil
			case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
				return floatType, nil
			case reflect.String:
				return floatType, nil
			}
			return anyType, fmt.Errorf("invalid argument for float (type %s)", args[0])
		},
	},
	{
		Name:  "string",
		Fast:  String,
		Types: types(new(func(any any) string)),
	},
	{
		Name: "trim",
		Func: func(args ...any) (any, error) {
			if len(args) == 1 {
				return strings.TrimSpace(args[0].(string)), nil
			} else if len(args) == 2 {
				return strings.Trim(args[0].(string), args[1].(string)), nil
			} else {
				return nil, fmt.Errorf("invalid number of arguments for trim (expected 1 or 2, got %d)", len(args))
			}
		},
		Types: types(
			strings.TrimSpace,
			strings.Trim,
		),
	},
	{
		Name: "trimPrefix",
		Func: func(args ...any) (any, error) {
			s := " "
			if len(args) == 2 {
				s = args[1].(string)
			}
			return strings.TrimPrefix(args[0].(string), s), nil
		},
		Types: types(
			strings.TrimPrefix,
			new(func(string) string),
		),
	},
	{
		Name: "trimSuffix",
		Func: func(args ...any) (any, error) {
			s := " "
			if len(args) == 2 {
				s = args[1].(string)
			}
			return strings.TrimSuffix(args[0].(string), s), nil
		},
		Types: types(
			strings.TrimSuffix,
			new(func(string) string),
		),
	},
	{
		Name: "upper",
		Fast: func(arg any) any {
			return strings.ToUpper(arg.(string))
		},
		Types: types(strings.ToUpper),
	},
	{
		Name: "lower",
		Fast: func(arg any) any {
			return strings.ToLower(arg.(string))
		},
		Types: types(strings.ToLower),
	},
	{
		Name: "split",
		Func: func(args ...any) (any, error) {
			if len(args) == 2 {
				return strings.Split(args[0].(string), args[1].(string)), nil
			} else if len(args) == 3 {
				return strings.SplitN(args[0].(string), args[1].(string), runtime.ToInt(args[2])), nil
			} else {
				return nil, fmt.Errorf("invalid number of arguments for split (expected 2 or 3, got %d)", len(args))
			}
		},
		Types: types(
			strings.Split,
			strings.SplitN,
		),
	},
	{
		Name: "splitAfter",
		Func: func(args ...any) (any, error) {
			if len(args) == 2 {
				return strings.SplitAfter(args[0].(string), args[1].(string)), nil
			} else if len(args) == 3 {
				return strings.SplitAfterN(args[0].(string), args[1].(string), runtime.ToInt(args[2])), nil
			} else {
				return nil, fmt.Errorf("invalid number of arguments for splitAfter (expected 2 or 3, got %d)", len(args))
			}
		},
		Types: types(
			strings.SplitAfter,
			strings.SplitAfterN,
		),
	},
	{
		Name: "replace",
		Func: func(args ...any) (any, error) {
			if len(args) == 4 {
				return strings.Replace(args[0].(string), args[1].(string), args[2].(string), runtime.ToInt(args[3])), nil
			} else if len(args) == 3 {
				return strings.ReplaceAll(args[0].(string), args[1].(string), args[2].(string)), nil
			} else {
				return nil, fmt.Errorf("invalid number of arguments for replace (expected 3 or 4, got %d)", len(args))
			}
		},
		Types: types(
			strings.Replace,
			strings.ReplaceAll,
		),
	},
	{
		Name: "repeat",
		Func: func(args ...any) (any, error) {
			n := runtime.ToInt(args[1])
			if n > 1e6 {
				panic("memory budget exceeded")
			}
			return strings.Repeat(args[0].(string), n), nil
		},
		Types: types(strings.Repeat),
	},
	{
		Name: "join",
		Func: func(args ...any) (any, error) {
			glue := ""
			if len(args) == 2 {
				glue = args[1].(string)
			}
			switch args[0].(type) {
			case []string:
				return strings.Join(args[0].([]string), glue), nil
			case []any:
				var s []string
				for _, arg := range args[0].([]any) {
					s = append(s, arg.(string))
				}
				return strings.Join(s, glue), nil
			}
			return nil, fmt.Errorf("invalid argument for join (type %s)", reflect.TypeOf(args[0]))
		},
		Types: types(
			strings.Join,
			new(func([]any, string) string),
			new(func([]any) string),
			new(func([]string, string) string),
			new(func([]string) string),
		),
	},
	{
		Name: "indexOf",
		Func: func(args ...any) (any, error) {
			return strings.Index(args[0].(string), args[1].(string)), nil
		},
		Types: types(strings.Index),
	},
	{
		Name: "lastIndexOf",
		Func: func(args ...any) (any, error) {
			return strings.LastIndex(args[0].(string), args[1].(string)), nil
		},
		Types: types(strings.LastIndex),
	},
	{
		Name: "hasPrefix",
		Func: func(args ...any) (any, error) {
			return strings.HasPrefix(args[0].(string), args[1].(string)), nil
		},
		Types: types(strings.HasPrefix),
	},
	{
		Name: "hasSuffix",
		Func: func(args ...any) (any, error) {
			return strings.HasSuffix(args[0].(string), args[1].(string)), nil
		},
		Types: types(strings.HasSuffix),
	},
	{
		Name: "max",
		Func: Max,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) == 0 {
				return anyType, fmt.Errorf("not enough arguments to call max")
			}
			for _, arg := range args {
				switch kind(arg) {
				case reflect.Interface:
					return anyType, nil
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
				default:
					return anyType, fmt.Errorf("invalid argument for max (type %s)", arg)
				}
			}
			return args[0], nil
		},
	},
	{
		Name: "min",
		Func: Min,
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) == 0 {
				return anyType, fmt.Errorf("not enough arguments to call min")
			}
			for _, arg := range args {
				switch kind(arg) {
				case reflect.Interface:
					return anyType, nil
				case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:
				default:
					return anyType, fmt.Errorf("invalid argument for min (type %s)", arg)
				}
			}
			return args[0], nil
		},
	},
	{
		Name: "sum",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
				return nil, fmt.Errorf("cannot sum %s", v.Kind())
			}
			sum := int64(0)
			i := 0
			for ; i < v.Len(); i++ {
				it := deref(v.Index(i))
				if it.CanInt() {
					sum += it.Int()
				} else if it.CanFloat() {
					goto float
				} else {
					return nil, fmt.Errorf("cannot sum %s", it.Kind())
				}
			}
			return int(sum), nil
		float:
			fSum := float64(sum)
			for ; i < v.Len(); i++ {
				it := deref(v.Index(i))
				if it.CanInt() {
					fSum += float64(it.Int())
				} else if it.CanFloat() {
					fSum += it.Float()
				} else {
					return nil, fmt.Errorf("cannot sum %s", it.Kind())
				}
			}
			return fSum, nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Slice, reflect.Array:
			default:
				return anyType, fmt.Errorf("cannot sum %s", args[0])
			}
			return anyType, nil
		},
	},
	{
		Name: "mean",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
				return nil, fmt.Errorf("cannot mean %s", v.Kind())
			}
			if v.Len() == 0 {
				return 0.0, nil
			}
			sum := float64(0)
			i := 0
			for ; i < v.Len(); i++ {
				it := deref(v.Index(i))
				if it.CanInt() {
					sum += float64(it.Int())
				} else if it.CanFloat() {
					sum += it.Float()
				} else {
					return nil, fmt.Errorf("cannot mean %s", it.Kind())
				}
			}
			return sum / float64(i), nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Slice, reflect.Array:
			default:
				return anyType, fmt.Errorf("cannot avg %s", args[0])
			}
			return floatType, nil
		},
	},
	{
		Name: "median",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
				return nil, fmt.Errorf("cannot median %s", v.Kind())
			}
			if v.Len() == 0 {
				return 0.0, nil
			}
			s := make([]float64, v.Len())
			for i := 0; i < v.Len(); i++ {
				it := deref(v.Index(i))
				if it.CanInt() {
					s[i] = float64(it.Int())
				} else if it.CanFloat() {
					s[i] = it.Float()
				} else {
					return nil, fmt.Errorf("cannot median %s", it.Kind())
				}
			}
			sort.Float64s(s)
			if len(s)%2 == 0 {
				return (s[len(s)/2-1] + s[len(s)/2]) / 2, nil
			}
			return s[len(s)/2], nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Slice, reflect.Array:
			default:
				return anyType, fmt.Errorf("cannot median %s", args[0])
			}
			return floatType, nil
		},
	},
	{
		Name: "toJSON",
		Func: func(args ...any) (any, error) {
			b, err := json.MarshalIndent(args[0], "", "  ")
			if err != nil {
				return nil, err
			}
			return string(b), nil
		},
		Types: types(new(func(any) string)),
	},
	{
		Name: "fromJSON",
		Func: func(args ...any) (any, error) {
			var v any
			err := json.Unmarshal([]byte(args[0].(string)), &v)
			if err != nil {
				return nil, err
			}
			return v, nil
		},
		Types: types(new(func(string) any)),
	},
	{
		Name: "toBase64",
		Func: func(args ...any) (any, error) {
			return base64.StdEncoding.EncodeToString([]byte(args[0].(string))), nil
		},
		Types: types(new(func(string) string)),
	},
	{
		Name: "fromBase64",
		Func: func(args ...any) (any, error) {
			b, err := base64.StdEncoding.DecodeString(args[0].(string))
			if err != nil {
				return nil, err
			}
			return string(b), nil
		},
		Types: types(new(func(string) string)),
	},
	{
		Name: "now",
		Func: func(args ...any) (any, error) {
			return time.Now(), nil
		},
		Types: types(new(func() time.Time)),
	},
	{
		Name: "duration",
		Func: func(args ...any) (any, error) {
			return time.ParseDuration(args[0].(string))
		},
		Types: types(time.ParseDuration),
	},
	{
		Name: "date",
		Func: func(args ...any) (any, error) {
			date := args[0].(string)
			if len(args) == 2 {
				layout := args[1].(string)
				return time.Parse(layout, date)
			}
			if len(args) == 3 {
				layout := args[1].(string)
				timeZone := args[2].(string)
				tz, err := time.LoadLocation(timeZone)
				if err != nil {
					return nil, err
				}
				t, err := time.ParseInLocation(layout, date, tz)
				if err != nil {
					return nil, err
				}
				return t, nil
			}

			layouts := []string{
				"2006-01-02",
				"15:04:05",
				"2006-01-02 15:04:05",
				time.RFC3339,
				time.RFC822,
				time.RFC850,
				time.RFC1123,
			}
			for _, layout := range layouts {
				t, err := time.Parse(layout, date)
				if err == nil {
					return t, nil
				}
			}
			return nil, fmt.Errorf("invalid date %s", date)
		},
		Types: types(
			new(func(string) time.Time),
			new(func(string, string) time.Time),
			new(func(string, string, string) time.Time),
		),
	},
	{
		Name: "first",
		Func: func(args ...any) (any, error) {
			defer func() {
				if r := recover(); r != nil {
					return
				}
			}()
			return runtime.Fetch(args[0], 0), nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface:
				return anyType, nil
			case reflect.Slice, reflect.Array:
				return args[0].Elem(), nil
			}
			return anyType, fmt.Errorf("cannot get first element from %s", args[0])
		},
	},
	{
		Name: "last",
		Func: func(args ...any) (any, error) {
			defer func() {
				if r := recover(); r != nil {
					return
				}
			}()
			return runtime.Fetch(args[0], -1), nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface:
				return anyType, nil
			case reflect.Slice, reflect.Array:
				return args[0].Elem(), nil
			}
			return anyType, fmt.Errorf("cannot get last element from %s", args[0])
		},
	},
	{
		Name: "get",
		Func: func(args ...any) (out any, err error) {
			defer func() {
				if r := recover(); r != nil {
					return
				}
			}()
			return runtime.Fetch(args[0], args[1]), nil
		},
	},
	{
		Name: "take",
		Func: func(args ...any) (any, error) {
			if len(args) != 2 {
				return nil, fmt.Errorf("invalid number of arguments (expected 2, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
				return nil, fmt.Errorf("cannot take from %s", v.Kind())
			}
			n := reflect.ValueOf(args[1])
			if !n.CanInt() {
				return nil, fmt.Errorf("cannot take %s elements", n.Kind())
			}
			if n.Int() > int64(v.Len()) {
				return args[0], nil
			}
			return v.Slice(0, int(n.Int())).Interface(), nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 2 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 2, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Slice, reflect.Array:
			default:
				return anyType, fmt.Errorf("cannot take from %s", args[0])
			}
			switch kind(args[1]) {
			case reflect.Interface, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			default:
				return anyType, fmt.Errorf("cannot take %s elements", args[1])
			}
			return args[0], nil
		},
	},
	{
		Name: "keys",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Map {
				return nil, fmt.Errorf("cannot get keys from %s", v.Kind())
			}
			keys := v.MapKeys()
			out := make([]any, len(keys))
			for i, key := range keys {
				out[i] = key.Interface()
			}
			return out, nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface:
				return arrayType, nil
			case reflect.Map:
				return arrayType, nil
			}
			return anyType, fmt.Errorf("cannot get keys from %s", args[0])
		},
	},
	{
		Name: "values",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Map {
				return nil, fmt.Errorf("cannot get values from %s", v.Kind())
			}
			keys := v.MapKeys()
			out := make([]any, len(keys))
			for i, key := range keys {
				out[i] = v.MapIndex(key).Interface()
			}
			return out, nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface:
				return arrayType, nil
			case reflect.Map:
				return arrayType, nil
			}
			return anyType, fmt.Errorf("cannot get values from %s", args[0])
		},
	},
	{
		Name: "toPairs",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Map {
				return nil, fmt.Errorf("cannot transform %s to pairs", v.Kind())
			}
			keys := v.MapKeys()
			out := make([][2]any, len(keys))
			for i, key := range keys {
				out[i] = [2]any{key.Interface(), v.MapIndex(key).Interface()}
			}
			return out, nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Map:
				return arrayType, nil
			}
			return anyType, fmt.Errorf("cannot transform %s to pairs", args[0])
		},
	},
	{
		Name: "fromPairs",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
				return nil, fmt.Errorf("cannot transform %s from pairs", v)
			}
			out := reflect.MakeMap(mapType)
			for i := 0; i < v.Len(); i++ {
				pair := deref(v.Index(i))
				if pair.Kind() != reflect.Array && pair.Kind() != reflect.Slice {
					return nil, fmt.Errorf("invalid pair %v", pair)
				}
				if pair.Len() != 2 {
					return nil, fmt.Errorf("invalid pair length %v", pair)
				}
				key := pair.Index(0)
				value := pair.Index(1)
				out.SetMapIndex(key, value)
			}
			return out.Interface(), nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Slice, reflect.Array:
				return mapType, nil
			}
			return anyType, fmt.Errorf("cannot transform %s from pairs", args[0])
		},
	},
	{
		Name: "sort",
		Func: func(args ...any) (any, error) {
			if len(args) != 1 && len(args) != 2 {
				return nil, fmt.Errorf("invalid number of arguments (expected 1 or 2, got %d)", len(args))
			}

			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
				return nil, fmt.Errorf("cannot sort %s", v.Kind())
			}

			orderBy := OrderBy{}
			if len(args) == 2 {
				dir, err := ascOrDesc(args[1])
				if err != nil {
					return nil, err
				}
				orderBy.Desc = dir
			}

			sortable, err := copyArray(v, orderBy)
			if err != nil {
				return nil, err
			}
			sort.Sort(sortable)
			return sortable.Array, nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 1 && len(args) != 2 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 1 or 2, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Slice, reflect.Array:
			default:
				return anyType, fmt.Errorf("cannot sort %s", args[0])
			}
			if len(args) == 2 {
				switch kind(args[1]) {
				case reflect.String, reflect.Interface:
				default:
					return anyType, fmt.Errorf("invalid argument for sort (expected string, got %s)", args[1])
				}
			}
			return arrayType, nil
		},
	},
	{
		Name: "sortBy",
		Func: func(args ...any) (any, error) {
			if len(args) != 2 && len(args) != 3 {
				return nil, fmt.Errorf("invalid number of arguments (expected 2 or 3, got %d)", len(args))
			}

			v := reflect.ValueOf(args[0])
			if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
				return nil, fmt.Errorf("cannot sort %s", v.Kind())
			}

			orderBy := OrderBy{}

			field, ok := args[1].(string)
			if !ok {
				return nil, fmt.Errorf("invalid argument for sort (expected string, got %s)", reflect.TypeOf(args[1]))
			}
			orderBy.Field = field

			if len(args) == 3 {
				dir, err := ascOrDesc(args[2])
				if err != nil {
					return nil, err
				}
				orderBy.Desc = dir
			}

			sortable, err := copyArray(v, orderBy)
			if err != nil {
				return nil, err
			}
			sort.Sort(sortable)
			return sortable.Array, nil
		},
		Validate: func(args []reflect.Type) (reflect.Type, error) {
			if len(args) != 2 && len(args) != 3 {
				return anyType, fmt.Errorf("invalid number of arguments (expected 2 or 3, got %d)", len(args))
			}
			switch kind(args[0]) {
			case reflect.Interface, reflect.Slice, reflect.Array:
			default:
				return anyType, fmt.Errorf("cannot sort %s", args[0])
			}
			switch kind(args[1]) {
			case reflect.String, reflect.Interface:
			default:
				return anyType, fmt.Errorf("invalid argument for sort (expected string, got %s)", args[1])
			}
			if len(args) == 3 {
				switch kind(args[2]) {
				case reflect.String, reflect.Interface:
				default:
					return anyType, fmt.Errorf("invalid argument for sort (expected string, got %s)", args[1])
				}
			}
			return arrayType, nil
		},
	},
}

Functions

func Abs

func Abs(x any) any

func Ceil

func Ceil(x any) any

func Float

func Float(x any) any

func Floor

func Floor(x any) any

func Int

func Int(x any) any

func Len

func Len(x any) any

func Max

func Max(args ...any) (any, error)

func Min

func Min(args ...any) (any, error)

func Round

func Round(x any) any

func String

func String(arg any) any

func Type

func Type(arg any) any

Types

type OrderBy

type OrderBy struct {
	Field string
	Desc  bool
}

type Sortable

type Sortable struct {
	Array  []any
	Values []reflect.Value
	OrderBy
}

func (*Sortable) Len

func (s *Sortable) Len() int

func (*Sortable) Less

func (s *Sortable) Less(i, j int) bool

func (*Sortable) Swap

func (s *Sortable) Swap(i, j int)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL