Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Uint64 and Int64 types #472

Merged
merged 4 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
}
chipshort marked this conversation as resolved.
Show resolved Hide resolved