package runtime import ( "encoding/json" "fmt" "reflect" "strconv" "sync/atomic" "time" ) type Value interface { Bool() (bool, error) Int() (int64, error) Float() (float64, error) String() (string, error) Duration() (time.Duration, error) Slice() ([]Value, error) Map() (map[string]Value, error) Scan(any) error Load() any Store(any) } type atomicValue struct { atomic.Value } func (v *atomicValue) typeAssertError() error { return fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load())) } func (v *atomicValue) Bool() (bool, error) { switch value := v.Load().(type) { case bool: return value, nil case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64: return strconv.ParseBool(fmt.Sprint(value)) case string: return strconv.ParseBool(value) } return false, v.typeAssertError() } func (v *atomicValue) Int() (int64, error) { switch value := v.Load().(type) { case int: return int64(value), nil case int8: return int64(value), nil case int16: return int64(value), nil case int32: return int64(value), nil case int64: return value, nil case uint: return int64(value), nil case uint8: return int64(value), nil case uint16: return int64(value), nil case uint32: return int64(value), nil case uint64: return int64(value), nil case float32: return int64(value), nil case float64: return int64(value), nil case string: return strconv.ParseInt(value, 10, 64) } return 0, v.typeAssertError() } func (v *atomicValue) Float() (float64, error) { switch value := v.Load().(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64: return strconv.ParseFloat(fmt.Sprint(value), 64) case string: return strconv.ParseFloat(value, 64) } return 0, v.typeAssertError() } func (v *atomicValue) String() (string, error) { switch value := v.Load().(type) { case string: return value, nil case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64: return fmt.Sprint(value), nil case []byte: return string(value), nil case fmt.Stringer: return value.String(), nil } return "", v.typeAssertError() } func (v *atomicValue) Duration() (time.Duration, error) { value, err := v.Int() if err != nil { return 0, err } return time.Duration(value), nil } func (v *atomicValue) Slice() ([]Value, error) { values, ok := v.Load().([]any) if !ok { return nil, v.typeAssertError() } out := make([]Value, 0, len(values)) for _, value := range values { item := &atomicValue{} item.Store(value) out = append(out, item) } return out, nil } func (v *atomicValue) Map() (map[string]Value, error) { values, ok := v.Load().(map[string]any) if !ok { return nil, v.typeAssertError() } out := make(map[string]Value, len(values)) for key, value := range values { item := &atomicValue{} item.Store(value) out[key] = item } return out, nil } func (v *atomicValue) Scan(obj any) error { data, err := json.Marshal(v.Load()) if err != nil { return err } return json.Unmarshal(data, obj) } type errValue struct { err error } func (v errValue) Bool() (bool, error) { return false, v.err } func (v errValue) Int() (int64, error) { return 0, v.err } func (v errValue) Float() (float64, error) { return 0, v.err } func (v errValue) Duration() (time.Duration, error) { return 0, v.err } func (v errValue) String() (string, error) { return "", v.err } func (v errValue) Scan(any) error { return v.err } func (v errValue) Load() any { return nil } func (v errValue) Store(any) {} func (v errValue) Slice() ([]Value, error) { return nil, v.err } func (v errValue) Map() (map[string]Value, error) { return nil, v.err }