Skip to content

Commit 9ffddd4

Browse files
committed
feat: add alias resolution
Signed-off-by: Mark Sagi-Kazar <[email protected]>
1 parent a6d26bd commit 9ffddd4

File tree

7 files changed

+74
-17
lines changed

7 files changed

+74
-17
lines changed

basic.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ func ToBoolE(i any) (bool, error) {
5858

5959
return false, fmt.Errorf(errorMsg, i, i, false)
6060
default:
61+
if i, ok := resolveAlias(i); ok {
62+
return ToBoolE(i)
63+
}
64+
6165
return false, fmt.Errorf(errorMsg, i, i, false)
6266
}
6367
}
@@ -114,7 +118,11 @@ func ToStringE(i any) (string, error) {
114118
case error:
115119
return s.Error(), nil
116120
default:
117-
if i, ok := indirect(s); ok {
121+
if i, ok := indirect(i); ok {
122+
return ToStringE(i)
123+
}
124+
125+
if i, ok := resolveAlias(i); ok {
118126
return ToStringE(i)
119127
}
120128

basic_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ func TestBool(t *testing.T) {
7777
{int32(-1), true, false},
7878
{int64(-1), true, false},
7979

80+
// Alias
81+
{MyBool(true), true, false},
82+
{MyBool(false), false, false},
83+
8084
// Failure cases
8185
{"test", false, true},
8286
{testing.T{}, false, true},
@@ -124,6 +128,10 @@ func TestString(t *testing.T) {
124128
{template.CSS("a"), "a", false},
125129
{template.HTMLAttr("a"), "a", false},
126130

131+
// Alias
132+
{MyString("foo"), "foo", false},
133+
134+
// Stringer and error
127135
{foo{val: "bar"}, "bar", false},
128136
{fu{val: "bar"}, "bar", false},
129137

cast_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,19 @@ func BenchmarkCast(b *testing.B) {
223223
}
224224
})
225225
}
226+
227+
// Alias types for alias testing
228+
type MyString string
229+
type MyBool bool
230+
type MyInt int
231+
type MyInt8 int8
232+
type MyInt16 int16
233+
type MyInt32 int32
234+
type MyInt64 int64
235+
type MyUint uint
236+
type MyUint8 uint8
237+
type MyUint16 uint16
238+
type MyUint32 uint32
239+
type MyUint64 uint64
240+
type MyFloat32 float32
241+
type MyFloat64 float64

number.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ func toNumberE[T Number](i any, parseFn func(string) (T, error)) (T, error) {
183183

184184
return T(s.Float64()), nil
185185
default:
186+
if i, ok := resolveAlias(i); ok {
187+
return toNumberE(i, parseFn)
188+
}
189+
186190
return 0, fmt.Errorf(errorMsg, i, i, n)
187191
}
188192
}
@@ -333,6 +337,10 @@ func toUnsignedNumberE[T Number](i any, parseFn func(string) (T, error)) (T, err
333337

334338
return T(v), nil
335339
default:
340+
if i, ok := resolveAlias(i); ok {
341+
return toUnsignedNumberE(i, parseFn)
342+
}
343+
336344
return 0, fmt.Errorf(errorMsg, i, i, n)
337345
}
338346
}

number_test.go

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ var numberContexts = map[string]numberContext{
4747
generic: toAny(cast.ToNumber[int]),
4848
specificErr: toAnyErr(cast.ToIntE),
4949
genericErr: toAnyErr(cast.ToNumberE[int]),
50-
samples: []any{int(0), int(1), int(8), int(-8), int(8), int(-8), math.MinInt, math.MaxInt, new(big.Int).Sub(big.NewInt(math.MinInt), big.NewInt(1)).String(), new(big.Int).Add(big.NewInt(math.MaxInt), big.NewInt(1)).String()},
50+
samples: []any{int(0), int(1), int(8), int(-8), int(8), int(-8), MyInt(8), math.MinInt, math.MaxInt, new(big.Int).Sub(big.NewInt(math.MinInt), big.NewInt(1)).String(), new(big.Int).Add(big.NewInt(math.MaxInt), big.NewInt(1)).String()},
5151
},
5252
"int8": {
5353
to: toAny(cast.To[int8]),
@@ -56,7 +56,7 @@ var numberContexts = map[string]numberContext{
5656
generic: toAny(cast.ToNumber[int8]),
5757
specificErr: toAnyErr(cast.ToInt8E),
5858
genericErr: toAnyErr(cast.ToNumberE[int8]),
59-
samples: []any{int8(0), int8(1), int8(8), int8(-8), int8(8), int8(-8), int8(math.MinInt8), int8(math.MaxInt8), "-129", "128"},
59+
samples: []any{int8(0), int8(1), int8(8), int8(-8), int8(8), int8(-8), MyInt8(8), int8(math.MinInt8), int8(math.MaxInt8), "-129", "128"},
6060
},
6161
"int16": {
6262
to: toAny(cast.To[int16]),
@@ -65,7 +65,7 @@ var numberContexts = map[string]numberContext{
6565
generic: toAny(cast.ToNumber[int16]),
6666
specificErr: toAnyErr(cast.ToInt16E),
6767
genericErr: toAnyErr(cast.ToNumberE[int16]),
68-
samples: []any{int16(0), int16(1), int16(8), int16(-8), int16(8), int16(-8), int16(math.MinInt16), int16(math.MaxInt16), "-32769", "32768"},
68+
samples: []any{int16(0), int16(1), int16(8), int16(-8), int16(8), int16(-8), MyInt16(8), int16(math.MinInt16), int16(math.MaxInt16), "-32769", "32768"},
6969
},
7070
"int32": {
7171
to: toAny(cast.To[int32]),
@@ -74,7 +74,7 @@ var numberContexts = map[string]numberContext{
7474
generic: toAny(cast.ToNumber[int32]),
7575
specificErr: toAnyErr(cast.ToInt32E),
7676
genericErr: toAnyErr(cast.ToNumberE[int32]),
77-
samples: []any{int32(0), int32(1), int32(8), int32(-8), int32(8), int32(-8), int32(math.MinInt32), int32(math.MaxInt32), "-2147483649", "2147483648"},
77+
samples: []any{int32(0), int32(1), int32(8), int32(-8), int32(8), int32(-8), MyInt32(8), int32(math.MinInt32), int32(math.MaxInt32), "-2147483649", "2147483648"},
7878
},
7979
"int64": {
8080
to: toAny(cast.To[int64]),
@@ -83,7 +83,7 @@ var numberContexts = map[string]numberContext{
8383
generic: toAny(cast.ToNumber[int64]),
8484
specificErr: toAnyErr(cast.ToInt64E),
8585
genericErr: toAnyErr(cast.ToNumberE[int64]),
86-
samples: []any{int64(0), int64(1), int64(8), int64(-8), int64(8), int64(-8), int64(math.MinInt64), int64(math.MaxInt64), "-9223372036854775809", "9223372036854775808"},
86+
samples: []any{int64(0), int64(1), int64(8), int64(-8), int64(8), int64(-8), MyInt64(8), int64(math.MinInt64), int64(math.MaxInt64), "-9223372036854775809", "9223372036854775808"},
8787
},
8888
"uint": {
8989
to: toAny(cast.To[uint]),
@@ -92,7 +92,7 @@ var numberContexts = map[string]numberContext{
9292
generic: toAny(cast.ToNumber[uint]),
9393
specificErr: toAnyErr(cast.ToUintE),
9494
genericErr: toAnyErr(cast.ToNumberE[uint]),
95-
samples: []any{uint(0), uint(1), uint(8), uint(0), uint(8), uint(0), uint(0), uint(math.MaxUint), nil, nil},
95+
samples: []any{uint(0), uint(1), uint(8), uint(0), uint(8), uint(0), MyUint(8), uint(0), uint(math.MaxUint), nil, nil},
9696
},
9797
"uint8": {
9898
to: toAny(cast.To[uint8]),
@@ -101,7 +101,7 @@ var numberContexts = map[string]numberContext{
101101
generic: toAny(cast.ToNumber[uint8]),
102102
specificErr: toAnyErr(cast.ToUint8E),
103103
genericErr: toAnyErr(cast.ToNumberE[uint8]),
104-
samples: []any{uint8(0), uint8(1), uint8(8), uint8(0), uint8(8), uint8(0), uint8(0), uint8(math.MaxUint8), "-1", "256"},
104+
samples: []any{uint8(0), uint8(1), uint8(8), uint8(0), uint8(8), uint8(0), MyUint8(8), uint8(0), uint8(math.MaxUint8), "-1", "256"},
105105
},
106106
"uint16": {
107107
to: toAny(cast.To[uint16]),
@@ -110,7 +110,7 @@ var numberContexts = map[string]numberContext{
110110
generic: toAny(cast.ToNumber[uint16]),
111111
specificErr: toAnyErr(cast.ToUint16E),
112112
genericErr: toAnyErr(cast.ToNumberE[uint16]),
113-
samples: []any{uint16(0), uint16(1), uint16(8), uint16(0), uint16(8), uint16(0), uint16(0), uint16(math.MaxUint16), "-1", "65536"},
113+
samples: []any{uint16(0), uint16(1), uint16(8), uint16(0), uint16(8), uint16(0), MyUint16(8), uint16(0), uint16(math.MaxUint16), "-1", "65536"},
114114
},
115115
"uint32": {
116116
to: toAny(cast.To[uint32]),
@@ -119,7 +119,7 @@ var numberContexts = map[string]numberContext{
119119
generic: toAny(cast.ToNumber[uint32]),
120120
specificErr: toAnyErr(cast.ToUint32E),
121121
genericErr: toAnyErr(cast.ToNumberE[uint32]),
122-
samples: []any{uint32(0), uint32(1), uint32(8), uint32(0), uint32(8), uint32(0), uint32(0), uint32(math.MaxUint32), "-1", "4294967296"},
122+
samples: []any{uint32(0), uint32(1), uint32(8), uint32(0), uint32(8), uint32(0), MyUint32(8), uint32(0), uint32(math.MaxUint32), "-1", "4294967296"},
123123
},
124124
"uint64": {
125125
to: toAny(cast.To[uint64]),
@@ -128,7 +128,7 @@ var numberContexts = map[string]numberContext{
128128
generic: toAny(cast.ToNumber[uint64]),
129129
specificErr: toAnyErr(cast.ToUint64E),
130130
genericErr: toAnyErr(cast.ToNumberE[uint64]),
131-
samples: []any{uint64(0), uint64(1), uint64(8), uint64(0), uint64(8), uint64(0), uint64(0), uint64(math.MaxUint64), "-1", "18446744073709551616"},
131+
samples: []any{uint64(0), uint64(1), uint64(8), uint64(0), uint64(8), uint64(0), MyUint64(8), uint64(0), uint64(math.MaxUint64), "-1", "18446744073709551616"},
132132
},
133133
"float32": {
134134
to: toAny(cast.To[float32]),
@@ -137,7 +137,7 @@ var numberContexts = map[string]numberContext{
137137
generic: toAny(cast.ToNumber[float32]),
138138
specificErr: toAnyErr(cast.ToFloat32E),
139139
genericErr: toAnyErr(cast.ToNumberE[float32]),
140-
samples: []any{float32(0), float32(1), float32(8), float32(-8), float32(8.31), float32(-8.31), float32(-math.MaxFloat32), float32(math.MaxFloat32), nil, nil},
140+
samples: []any{float32(0), float32(1), float32(8), float32(-8), float32(8.31), float32(-8.31), MyFloat32(8), float32(-math.MaxFloat32), float32(math.MaxFloat32), nil, nil},
141141
},
142142
"float64": {
143143
to: toAny(cast.To[float64]),
@@ -146,7 +146,7 @@ var numberContexts = map[string]numberContext{
146146
generic: toAny(cast.ToNumber[float64]),
147147
specificErr: toAnyErr(cast.ToFloat64E),
148148
genericErr: toAnyErr(cast.ToNumberE[float64]),
149-
samples: []any{float64(0), float64(1), float64(8), float64(-8), float64(8.31), float64(-8.31), float64(-math.MaxFloat64), float64(math.MaxFloat64), nil, nil},
149+
samples: []any{float64(0), float64(1), float64(8), float64(-8), float64(8.31), float64(-8.31), MyFloat64(8), float64(-math.MaxFloat64), float64(math.MaxFloat64), nil, nil},
150150
},
151151
}
152152

@@ -157,10 +157,11 @@ func generateNumberTestCases(samples []any) []testCase {
157157
eightNegative := samples[3]
158158
eightPoint31 := samples[4]
159159
eightPoint31Negative := samples[5]
160-
min := samples[6]
161-
max := samples[7]
162-
underflowString := samples[8]
163-
overflowString := samples[9]
160+
aliasEight := samples[6]
161+
min := samples[7]
162+
max := samples[8]
163+
underflowString := samples[9]
164+
overflowString := samples[10]
164165

165166
_ = min
166167
_ = max
@@ -222,6 +223,11 @@ func generateNumberTestCases(samples []any) []testCase {
222223
{json.Number("-8.31"), eightPoint31Negative, isUint},
223224
{json.Number(""), zero, false},
224225

226+
// Aliases
227+
{aliasEight, eight, false},
228+
{MyString("8"), eight, false},
229+
{MyBool(true), one, false},
230+
225231
// Failure cases
226232
{"test", zero, true},
227233
{testing.T{}, zero, true},

time.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ func ToDurationE(i any) (time.Duration, error) {
8888

8989
return time.ParseDuration(s)
9090
default:
91+
if i, ok := resolveAlias(i); ok {
92+
return ToDurationE(i)
93+
}
94+
9195
return 0, fmt.Errorf(errorMsg, i, i, time.Duration(0))
9296
}
9397
}

time_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ func TestTime(t *testing.T) {
6666
}
6767

6868
func TestDuration(t *testing.T) {
69+
type MyDuration time.Duration
70+
6971
var expected time.Duration = 5
7072

7173
testCases := []testCase{
@@ -92,6 +94,11 @@ func TestDuration(t *testing.T) {
9294
{string("5m"), time.Minute * expected, false},
9395
{string("5h"), time.Hour * expected, false},
9496

97+
// Aliases
98+
{MyInt(5), expected, false},
99+
{MyString("5"), expected, false},
100+
{MyDuration(5), expected, false},
101+
95102
// Failure cases
96103
{"test", time.Duration(0), true},
97104
{testing.T{}, time.Duration(0), true},

0 commit comments

Comments
 (0)