From b0445ca89205ba012716b4373da918828a36fb7b Mon Sep 17 00:00:00 2001 From: Yan Mikhailov Date: Tue, 19 Mar 2019 12:04:41 +0200 Subject: [PATCH 1/3] cast json.Number --- cast_test.go | 27 ++++++++++++++++- caste.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ types.go | 11 +++++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 types.go diff --git a/cast_test.go b/cast_test.go index d9a1479..9512286 100644 --- a/cast_test.go +++ b/cast_test.go @@ -6,6 +6,7 @@ package cast import ( + "encoding/json" "fmt" "html/template" "testing" @@ -30,6 +31,7 @@ func TestToUintE(t *testing.T) { {uint16(8), 8, false}, {uint32(8), 8, false}, {uint64(8), 8, false}, + {json.Number("8"), 8, false}, {float32(8.31), 8, false}, {float64(8.31), 8, false}, {true, 1, false}, @@ -45,6 +47,7 @@ func TestToUintE(t *testing.T) { {float32(-8.31), 0, true}, {float64(-8.31), 0, true}, {"-8", 0, true}, + {json.Number("-8"), 0, true}, {"test", 0, true}, {testing.T{}, 0, true}, } @@ -83,6 +86,7 @@ func TestToUint64E(t *testing.T) { {uint16(8), 8, false}, {uint32(8), 8, false}, {uint64(8), 8, false}, + {json.Number("8"), 8, false}, {float32(8.31), 8, false}, {float64(8.31), 8, false}, {true, 1, false}, @@ -98,6 +102,7 @@ func TestToUint64E(t *testing.T) { {float32(-8.31), 0, true}, {float64(-8.31), 0, true}, {"-8", 0, true}, + {json.Number("-8"), 0, true}, {"test", 0, true}, {testing.T{}, 0, true}, } @@ -136,12 +141,14 @@ func TestToUint32E(t *testing.T) { {uint16(8), 8, false}, {uint32(8), 8, false}, {uint64(8), 8, false}, + {json.Number("8"), 8, false}, {float32(8.31), 8, false}, {float64(8.31), 8, false}, {true, 1, false}, {false, 0, false}, {"8", 8, false}, {nil, 0, false}, + // errors {int(-8), 0, true}, {int8(-8), 0, true}, {int16(-8), 0, true}, @@ -150,7 +157,7 @@ func TestToUint32E(t *testing.T) { {float32(-8.31), 0, true}, {float64(-8.31), 0, true}, {"-8", 0, true}, - // errors + {json.Number("-8"), 0, true}, {"test", 0, true}, {testing.T{}, 0, true}, } @@ -189,6 +196,7 @@ func TestToUint16E(t *testing.T) { {uint16(8), 8, false}, {uint32(8), 8, false}, {uint64(8), 8, false}, + {json.Number("8"), 8, false}, {float32(8.31), 8, false}, {float64(8.31), 8, false}, {true, 1, false}, @@ -204,6 +212,7 @@ func TestToUint16E(t *testing.T) { {float32(-8.31), 0, true}, {float64(-8.31), 0, true}, {"-8", 0, true}, + {json.Number("-8"), 0, true}, {"test", 0, true}, {testing.T{}, 0, true}, } @@ -242,6 +251,7 @@ func TestToUint8E(t *testing.T) { {uint16(8), 8, false}, {uint32(8), 8, false}, {uint64(8), 8, false}, + {json.Number("8"), 8, false}, {float32(8.31), 8, false}, {float64(8.31), 8, false}, {true, 1, false}, @@ -257,6 +267,7 @@ func TestToUint8E(t *testing.T) { {float32(-8.31), 0, true}, {float64(-8.31), 0, true}, {"-8", 0, true}, + {json.Number("-8"), 0, true}, {"test", 0, true}, {testing.T{}, 0, true}, } @@ -300,9 +311,11 @@ func TestToIntE(t *testing.T) { {true, 1, false}, {false, 0, false}, {"8", 8, false}, + {json.Number("8"), 8, false}, {nil, 0, false}, // errors {"test", 0, true}, + {json.Number("test"), 0, true}, {testing.T{}, 0, true}, } @@ -345,9 +358,11 @@ func TestToInt64E(t *testing.T) { {true, 1, false}, {false, 0, false}, {"8", 8, false}, + {json.Number("8"), 8, false}, {nil, 0, false}, // errors {"test", 0, true}, + {json.Number("test"), 0, true}, {testing.T{}, 0, true}, } @@ -390,9 +405,11 @@ func TestToInt32E(t *testing.T) { {true, 1, false}, {false, 0, false}, {"8", 8, false}, + {json.Number("8"), 8, false}, {nil, 0, false}, // errors {"test", 0, true}, + {json.Number("test"), 0, true}, {testing.T{}, 0, true}, } @@ -435,9 +452,11 @@ func TestToInt16E(t *testing.T) { {true, 1, false}, {false, 0, false}, {"8", 8, false}, + {json.Number("8"), 8, false}, {nil, 0, false}, // errors {"test", 0, true}, + {json.Number("test"), 0, true}, {testing.T{}, 0, true}, } @@ -480,9 +499,11 @@ func TestToInt8E(t *testing.T) { {true, 1, false}, {false, 0, false}, {"8", 8, false}, + {json.Number("8"), 8, false}, {nil, 0, false}, // errors {"test", 0, true}, + {json.Number("test"), 0, true}, {testing.T{}, 0, true}, } @@ -523,10 +544,12 @@ func TestToFloat64E(t *testing.T) { {float32(8), 8, false}, {float64(8.31), 8.31, false}, {"8", 8, false}, + {json.Number("8.31"), 8.31, false}, {true, 1, false}, {false, 0, false}, // errors {"test", 0, true}, + {json.Number("test"), 0, true}, {testing.T{}, 0, true}, } @@ -567,10 +590,12 @@ func TestToFloat32E(t *testing.T) { {float32(8.31), 8.31, false}, {float64(8.31), 8.31, false}, {"8", 8, false}, + {json.Number("8.31"), 8.31, false}, {true, 1, false}, {false, 0, false}, // errors {"test", 0, true}, + {json.Number("test"), 0, true}, {testing.T{}, 0, true}, } diff --git a/caste.go b/caste.go index a4859fb..0d44149 100644 --- a/caste.go +++ b/caste.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "html/template" + "math" "reflect" "strconv" "strings" @@ -131,6 +132,12 @@ func ToFloat64E(i interface{}) (float64, error) { return 1, nil } return 0, nil + case Float64er: + v, err := s.Float64() + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + } + return v, nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) } @@ -176,6 +183,15 @@ func ToFloat32E(i interface{}) (float32, error) { return 1, nil } return 0, nil + case Float64er: + v, err := s.Float64() + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + } + if v > math.MaxFloat32 { + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + } + return float32(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) } @@ -223,6 +239,12 @@ func ToInt64E(i interface{}) (int64, error) { return 0, nil case nil: return 0, nil + case Int64er: + v, err := s.Int64() + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + } + return v, nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) } @@ -270,6 +292,15 @@ func ToInt32E(i interface{}) (int32, error) { return 0, nil case nil: return 0, nil + case Int64er: + v, err := s.Int64() + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + } + if v > math.MaxInt32 { + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + } + return int32(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) } @@ -317,6 +348,15 @@ func ToInt16E(i interface{}) (int16, error) { return 0, nil case nil: return 0, nil + case Int64er: + v, err := s.Int64() + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + } + if v > math.MaxInt16 { + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + } + return int16(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) } @@ -364,6 +404,15 @@ func ToInt8E(i interface{}) (int8, error) { return 0, nil case nil: return 0, nil + case Int64er: + v, err := s.Int64() + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + } + if v > math.MaxInt8 { + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + } + return int8(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) } @@ -411,6 +460,12 @@ func ToIntE(i interface{}) (int, error) { return 0, nil case nil: return 0, nil + case Int64er: + v, err := s.Int64() + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + } + return int(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) } @@ -479,6 +534,12 @@ func ToUintE(i interface{}) (uint, error) { return 0, nil case nil: return 0, nil + case fmt.Stringer: + v, err := strconv.ParseUint(s.String(), 10, 64) + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) + } + return uint(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) } @@ -547,6 +608,12 @@ func ToUint64E(i interface{}) (uint64, error) { return 0, nil case nil: return 0, nil + case fmt.Stringer: + v, err := strconv.ParseUint(s.String(), 10, 64) + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) + } + return v, nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) } @@ -615,6 +682,12 @@ func ToUint32E(i interface{}) (uint32, error) { return 0, nil case nil: return 0, nil + case fmt.Stringer: + v, err := strconv.ParseUint(s.String(), 10, 32) + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) + } + return uint32(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) } @@ -683,6 +756,12 @@ func ToUint16E(i interface{}) (uint16, error) { return 0, nil case nil: return 0, nil + case fmt.Stringer: + v, err := strconv.ParseUint(s.String(), 10, 16) + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) + } + return uint16(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) } @@ -751,6 +830,12 @@ func ToUint8E(i interface{}) (uint8, error) { return 0, nil case nil: return 0, nil + case fmt.Stringer: + v, err := strconv.ParseUint(s.String(), 10, 8) + if err != nil { + return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) + } + return uint8(v), nil default: return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) } diff --git a/types.go b/types.go new file mode 100644 index 0000000..91c9261 --- /dev/null +++ b/types.go @@ -0,0 +1,11 @@ +package cast + +type ( + Float64er interface { + Float64() (float64, error) + } + + Int64er interface { + Int64() (int64, error) + } +) From a4d8cc2a71bf5f5262e934cc53759e82e772504c Mon Sep 17 00:00:00 2001 From: Yan Mikhailov Date: Tue, 19 Mar 2019 14:06:03 +0200 Subject: [PATCH 2/3] changed types to unexoprted --- caste.go | 14 +++++++------- types.go | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/caste.go b/caste.go index 0d44149..8c01e48 100644 --- a/caste.go +++ b/caste.go @@ -132,7 +132,7 @@ func ToFloat64E(i interface{}) (float64, error) { return 1, nil } return 0, nil - case Float64er: + case float64er: v, err := s.Float64() if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) @@ -183,7 +183,7 @@ func ToFloat32E(i interface{}) (float32, error) { return 1, nil } return 0, nil - case Float64er: + case float64er: v, err := s.Float64() if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) @@ -239,7 +239,7 @@ func ToInt64E(i interface{}) (int64, error) { return 0, nil case nil: return 0, nil - case Int64er: + case int64er: v, err := s.Int64() if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) @@ -292,7 +292,7 @@ func ToInt32E(i interface{}) (int32, error) { return 0, nil case nil: return 0, nil - case Int64er: + case int64er: v, err := s.Int64() if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) @@ -348,7 +348,7 @@ func ToInt16E(i interface{}) (int16, error) { return 0, nil case nil: return 0, nil - case Int64er: + case int64er: v, err := s.Int64() if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) @@ -404,7 +404,7 @@ func ToInt8E(i interface{}) (int8, error) { return 0, nil case nil: return 0, nil - case Int64er: + case int64er: v, err := s.Int64() if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) @@ -460,7 +460,7 @@ func ToIntE(i interface{}) (int, error) { return 0, nil case nil: return 0, nil - case Int64er: + case int64er: v, err := s.Int64() if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) diff --git a/types.go b/types.go index 91c9261..6451f86 100644 --- a/types.go +++ b/types.go @@ -1,11 +1,11 @@ package cast type ( - Float64er interface { + float64er interface { Float64() (float64, error) } - Int64er interface { + int64er interface { Int64() (int64, error) } ) From be350e81ccd59eaa0a4b309c2aca26c259bc4239 Mon Sep 17 00:00:00 2001 From: Yan Mikhailov Date: Tue, 19 Mar 2019 14:07:33 +0200 Subject: [PATCH 3/3] fix, use json.Number instead of fmt.Stringer --- caste.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/caste.go b/caste.go index 8c01e48..00a20cc 100644 --- a/caste.go +++ b/caste.go @@ -534,7 +534,7 @@ func ToUintE(i interface{}) (uint, error) { return 0, nil case nil: return 0, nil - case fmt.Stringer: + case json.Number: v, err := strconv.ParseUint(s.String(), 10, 64) if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) @@ -608,7 +608,7 @@ func ToUint64E(i interface{}) (uint64, error) { return 0, nil case nil: return 0, nil - case fmt.Stringer: + case json.Number: v, err := strconv.ParseUint(s.String(), 10, 64) if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) @@ -682,7 +682,7 @@ func ToUint32E(i interface{}) (uint32, error) { return 0, nil case nil: return 0, nil - case fmt.Stringer: + case json.Number: v, err := strconv.ParseUint(s.String(), 10, 32) if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) @@ -756,7 +756,7 @@ func ToUint16E(i interface{}) (uint16, error) { return 0, nil case nil: return 0, nil - case fmt.Stringer: + case json.Number: v, err := strconv.ParseUint(s.String(), 10, 16) if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) @@ -830,7 +830,7 @@ func ToUint8E(i interface{}) (uint8, error) { return 0, nil case nil: return 0, nil - case fmt.Stringer: + case json.Number: v, err := strconv.ParseUint(s.String(), 10, 8) if err != nil { return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i)