Skip to content

Commit

Permalink
Merge pull request #472 from CosmWasm/int-types
Browse files Browse the repository at this point in the history
Add `Uint64` and `Int64` types
  • Loading branch information
chipshort authored Nov 20, 2023
2 parents 016e775 + 4cd270e commit 1ebd46e
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 5 deletions.
4 changes: 2 additions & 2 deletions spec/Specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ type Params struct {
type BlockInfo struct {
// block height this transaction is executed
Height uint64 `json:"height"`
// time in nanoseconds since unix epoch. Uses string to ensure JavaScript compatibility.
Time uint64 `json:"time,string"`
// time in nanoseconds since unix epoch. Uses Uint64 to ensure JavaScript compatibility.
Time Uint64 `json:"time"`
ChainID string `json:"chain_id"`
}

Expand Down
4 changes: 2 additions & 2 deletions types/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ type Env struct {
type BlockInfo struct {
// block height this transaction is executed
Height uint64 `json:"height"`
// time in nanoseconds since unix epoch. Uses string to ensure JavaScript compatibility.
Time uint64 `json:"time,string"`
// time in nanoseconds since unix epoch. Uses Uint64 to ensure JavaScript compatibility.
Time Uint64 `json:"time"`
ChainID string `json:"chain_id"`
}

Expand Down
2 changes: 1 addition & 1 deletion types/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ func TestBlockInfoDeserialization(t *testing.T) {

// Empty string is not a valid uint64 string
err = json.Unmarshal([]byte(`{"height":0,"time":"","chain_id":""}`), &block)
require.ErrorContains(t, err, "invalid use of ,string struct tag, trying to unmarshal \"\" into uint64")
require.ErrorContains(t, err, "cannot unmarshal \"\" into Uint64, failed to parse integer")
}
41 changes: 41 additions & 0 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,50 @@ package types

import (
"encoding/json"
"fmt"
"strconv"
)

// Uint64 is a wrapper for uint64, but it is marshalled to and from JSON as a string
type Uint64 uint64

func (u Uint64) MarshalJSON() ([]byte, error) {
return json.Marshal(strconv.FormatUint(uint64(u), 10))
}

func (u *Uint64) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return fmt.Errorf("cannot unmarshal %s into Uint64, expected string-encoded integer", data)
}
v, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return fmt.Errorf("cannot unmarshal %s into Uint64, failed to parse integer", data)
}
*u = Uint64(v)
return nil
}

// Int64 is a wrapper for int64, but it is marshalled to and from JSON as a string
type Int64 int64

func (i Int64) MarshalJSON() ([]byte, error) {
return json.Marshal(strconv.FormatInt(int64(i), 10))
}

func (i *Int64) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return fmt.Errorf("cannot unmarshal %s into Int64, expected string-encoded integer", data)
}
v, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return fmt.Errorf("cannot unmarshal %s into Int64, failed to parse integer", data)
}
*i = Int64(v)
return nil
}

// HumanAddress is a printable (typically bech32 encoded) address string. Just use it as a label for developers.
type HumanAddress = string

Expand Down
86 changes: 86 additions & 0 deletions types/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package types

import (
"encoding/json"
"math"
"testing"

"github.com/stretchr/testify/require"
)

func TestUint64JSON(t *testing.T) {
var u Uint64

// test unmarshal
err := json.Unmarshal([]byte(`"123"`), &u)
require.NoError(t, err)
require.Equal(t, uint64(123), uint64(u))
// test marshal
bz, err := json.Marshal(u)
require.NoError(t, err)
require.Equal(t, `"123"`, string(bz))

// test max value unmarshal
err = json.Unmarshal([]byte(`"18446744073709551615"`), &u)
require.NoError(t, err)
require.Equal(t, uint64(math.MaxUint64), uint64(u))
// test max value marshal
bz, err = json.Marshal(Uint64(uint64(math.MaxUint64)))
require.NoError(t, err)
require.Equal(t, `"18446744073709551615"`, string(bz))

// test max value + 1
err = json.Unmarshal([]byte(`"18446744073709551616"`), &u)
require.Error(t, err)

// test unquoted unmarshal
err = json.Unmarshal([]byte(`123`), &u)
require.EqualError(t, err, "cannot unmarshal 123 into Uint64, expected string-encoded integer")

// test empty string
err = json.Unmarshal([]byte(`""`), &u)
require.EqualError(t, err, "cannot unmarshal \"\" into Uint64, failed to parse integer")
}

func TestInt64JSON(t *testing.T) {
var i Int64

// test unmarshal
err := json.Unmarshal([]byte(`"-123"`), &i)
require.NoError(t, err)
require.Equal(t, int64(-123), int64(i))
// test marshal
bz, err := json.Marshal(i)
require.NoError(t, err)
require.Equal(t, `"-123"`, string(bz))

// test max value unmarshal
err = json.Unmarshal([]byte(`"9223372036854775807"`), &i)
require.NoError(t, err)
require.Equal(t, int64(math.MaxInt64), int64(i))
// test max value marshal
bz, err = json.Marshal(Int64(int64(math.MaxInt64)))
require.NoError(t, err)
require.Equal(t, `"9223372036854775807"`, string(bz))

// test max value + 1
err = json.Unmarshal([]byte(`"9223372036854775808"`), &i)
require.Error(t, err)

// test min value unmarshal
err = json.Unmarshal([]byte(`"-9223372036854775808"`), &i)
require.NoError(t, err)
require.Equal(t, int64(math.MinInt64), int64(i))
// test min value marshal
bz, err = json.Marshal(Int64(int64(math.MinInt64)))
require.NoError(t, err)
require.Equal(t, `"-9223372036854775808"`, string(bz))

// test unquoted unmarshal
err = json.Unmarshal([]byte(`-123`), &i)
require.EqualError(t, err, "cannot unmarshal -123 into Int64, expected string-encoded integer")

// test empty string
err = json.Unmarshal([]byte(`""`), &i)
require.EqualError(t, err, "cannot unmarshal \"\" into Int64, failed to parse integer")
}

0 comments on commit 1ebd46e

Please sign in to comment.