Files
upstream-corteza/server/pkg/expr/expr.go
upstream-mirror 7e385fc126
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:22:23 +05:00

148 lines
2.9 KiB
Go

package expr
import (
"fmt"
"strings"
)
var (
invalidPathErr = fmt.Errorf("invalid path format")
)
func PathBase(path string) string {
return strings.Split(path, ".")[0]
}
func Assign(base TypedValue, path string, val TypedValue) (err error) {
if _, ok := base.(FlatStore); ok {
return assignFlat(base, path, val)
}
return assignPath(base, path, val)
}
func assignFlat(base TypedValue, key string, val TypedValue) error {
switch fa := base.(type) {
case FieldAssigner:
return fa.AssignFieldValue(key, val)
case DeepFieldAssigner:
return fa.AssignFieldValue(&flatPath{key: key}, val)
default:
return fmt.Errorf("cannot set on unexpected type: %T", base)
}
}
// flatPath is a single-segment Pather for flat key assignment — no path splitting.
type flatPath struct {
key string
done bool
}
func (p *flatPath) String() string { return p.key }
func (p *flatPath) More() bool { return !p.done }
func (p *flatPath) IsLast() bool { return true }
func (p *flatPath) Get() string { return p.key }
func (p *flatPath) Rest() string { return "" }
func (p *flatPath) Next() error { p.done = true; return nil }
func assignPath(base TypedValue, path string, val TypedValue) (err error) {
pp := Path(path)
err = pp.Next()
if err != nil {
return
}
if !pp.More() {
panic("setting value with empty path")
}
var (
key = ""
)
// descend lower by the path but
// stop before the last part of the path
for !pp.IsLast() {
switch s := base.(type) {
case DeepFieldAssigner:
return s.AssignFieldValue(pp, val)
case FieldSelector:
key = pp.Get()
err = pp.Next()
if err != nil {
return
}
if base, err = s.Select(key); err != nil {
return err
}
default:
return fmt.Errorf("cannot set value on %s with path '%s'", base.Type(), path)
}
}
key = pp.Get()
// try with field setter first
// if not a FieldSetter it has to be a Selector
// that returns TypedValue that we can set
switch setter := base.(type) {
case DeepFieldAssigner:
return setter.AssignFieldValue(pp, val)
case FieldAssigner:
return setter.AssignFieldValue(key, val)
case FieldSelector:
if base, err = setter.Select(key); err != nil {
return err
}
return base.Assign(val)
default:
return fmt.Errorf("%T does not support value assigning with '%s'", base, path)
}
}
func Select(base TypedValue, path string) (out TypedValue, err error) {
pp := Path(path)
err = pp.Next()
if err != nil {
return
}
if !pp.More() {
panic("setting value with empty path")
}
var (
failure = fmt.Errorf("cannot get value from %s with path '%s'", base.Type(), path)
key string
)
// descend lower by the path but
// stop before the last part of the path
for pp.More() {
s, is := base.(FieldSelector)
if !is {
return nil, failure
}
key = pp.Get()
err = pp.Next()
if err != nil {
return
}
if base, err = s.Select(key); err != nil {
return nil, err
}
}
return base, nil
}