-
Notifications
You must be signed in to change notification settings - Fork 2
/
value.go
165 lines (142 loc) · 4.13 KB
/
value.go
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package sdktypes
import (
"encoding/base64"
"errors"
"fmt"
"time"
"github.com/araddon/dateparse"
"go.autokitteh.dev/autokitteh/internal/kittehs"
valuev1 "go.autokitteh.dev/autokitteh/proto/gen/go/autokitteh/values/v1"
"go.autokitteh.dev/autokitteh/sdk/sdklogger"
)
type Value struct{ object[*ValuePB, ValueTraits] }
var InvalidValue Value
type ValuePB = valuev1.Value
type ValueTraits struct{}
func validateValue(m *ValuePB) error {
return errors.Join(
objectField[SymbolValue]("symbol", m.Symbol),
objectField[ListValue]("list", m.List),
objectField[SetValue]("set", m.Set),
objectField[DictValue]("dict", m.Dict),
objectField[StructValue]("struct", m.Struct),
objectField[ModuleValue]("module", m.Module),
)
}
func (ValueTraits) Validate(m *ValuePB) error { return validateValue(m) }
func (ValueTraits) StrictValidate(m *ValuePB) error { return oneOfMessage(m) }
func ValueFromProto(m *ValuePB) (Value, error) { return FromProto[Value](m) }
func StrictValueFromProto(m *ValuePB) (Value, error) { return Strict(ValueFromProto(m)) }
func NewValue(cv concreteValue) Value {
switch cv := cv.(type) {
case NothingValue:
return Nothing
case IntegerValue:
return NewIntegerValue(cv.Value())
case FloatValue:
return NewFloatValue(cv.Value())
case BooleanValue:
return NewBooleanValue(cv.Value())
case StringValue:
return NewStringValue(cv.Value())
case BytesValue:
return NewBytesValue(cv.Value())
case DurationValue:
return NewDurationValue(cv.Value())
case TimeValue:
return NewTimeValue(cv.Value())
case SymbolValue:
return NewSymbolValue(cv.Symbol())
case ListValue:
return kittehs.Must1(NewListValue(cv.Values()))
case SetValue:
return kittehs.Must1(NewSetValue(cv.Values()))
case DictValue:
return kittehs.Must1(NewDictValue(cv.Items()))
case StructValue:
return kittehs.Must1(NewStructValue(cv.Ctor(), cv.Fields()))
case ModuleValue:
return kittehs.Must1(NewModuleValue(cv.Name(), cv.Members()))
default:
sdklogger.DPanic("unknown concrete value type")
}
return Value{}
}
var valueGetters = []func(Value) concreteValue{}
func registerValueGetter(f func(Value) concreteValue) {
valueGetters = append(valueGetters, f)
}
func (v Value) Concrete() concreteValue {
if !v.IsValid() {
return nil
}
for _, get := range valueGetters {
if c := get(v); c != nil {
return c
}
}
sdklogger.DPanic("unknown value type")
return nil
}
func (v Value) ToDuration() (time.Duration, error) {
switch v := v.Concrete().(type) {
case DurationValue:
return v.Value(), nil
case IntegerValue:
return time.Second * time.Duration(v.Value()), nil
case FloatValue:
return time.Duration(float64(time.Second) * v.Value()), nil
case StringValue:
return time.ParseDuration(v.Value())
default:
return 0, fmt.Errorf("value not convertible to duration")
}
}
func (v Value) ToTime() (time.Time, error) {
switch v := v.Concrete().(type) {
case TimeValue:
return v.Value(), nil
case StringValue:
return dateparse.ParseAny(v.Value())
case IntegerValue:
return time.Unix(v.Value(), 0), nil
default:
return time.Time{}, fmt.Errorf("value not convertible to time")
}
}
func (v Value) ToString() (string, error) {
switch v := v.Concrete().(type) {
case StringValue:
return v.Value(), nil
case IntegerValue:
return fmt.Sprintf("%d", v.Value()), nil
case FloatValue:
return fmt.Sprintf("%f", v.Value()), nil
case BooleanValue:
return fmt.Sprintf("%t", v.Value()), nil
case DurationValue:
return v.Value().String(), nil
case TimeValue:
return v.Value().String(), nil
case BytesValue:
return base64.StdEncoding.EncodeToString(v.Value()), nil
case SymbolValue:
return v.Symbol().String(), nil
default:
return "", errors.New("not convertible to string")
}
}
func (v Value) ToStringValuesMap() (map[string]Value, error) {
switch v := v.Concrete().(type) {
case DictValue:
return v.ToStringValuesMap()
case StructValue:
return v.Fields(), nil
case ModuleValue:
return v.Members(), nil
default:
return nil, errors.New("not convertible to map")
}
}
func (v Value) Unwrap() (any, error) { return UnwrapValue(v) }
func (v Value) UnwrapInto(dst any) error { return UnwrapValueInto(dst, v) }