package internal import ( "reflect" "strings" ) type Context struct { vars map[string]any } func NewContext(vars map[string]any) *Context { return &Context{vars: vars} } func (c *Context) Get(path string) (any, bool) { if c.vars == nil { return nil, false } return resolvePath(c.vars, path) } func resolvePath(current any, path string) (any, bool) { for seg := range strings.SplitSeq(path, ".") { if current == nil { return nil, false } switch v := current.(type) { case map[string]any: var ok bool current, ok = v[seg] if !ok { return nil, false } default: val := reflect.ValueOf(current) for val.Kind() == reflect.Pointer { val = val.Elem() } if val.Kind() != reflect.Struct { return nil, false } field := val.FieldByName(seg) if !field.IsValid() { field = findFieldIgnoreCase(val, seg) } if !field.IsValid() { return nil, false } current = field.Interface() } } return current, true } func findFieldIgnoreCase(v reflect.Value, name string) reflect.Value { typ := v.Type() for i := range typ.NumField() { f := typ.Field(i) if !f.IsExported() { continue } if strings.EqualFold(f.Name, name) { return v.Field(i) } } return reflect.Value{} }