github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/types/uint.go (about)

     1  // Go Substrate RPC Client (GSRPC) provides APIs and types around Polkadot and any Substrate-based chain RPC calls
     2  //
     3  // Copyright 2020 Stafi Protocol
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package types
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/stafiprotocol/go-substrate-rpc-client/pkg/scale"
    25  )
    26  
    27  // U8 is an unsigned 8-bit integer
    28  type U8 uint8
    29  
    30  // NewU8 creates a new U8 type
    31  func NewU8(u uint8) U8 {
    32  	return U8(u)
    33  }
    34  
    35  // UnmarshalJSON fills u with the JSON encoded byte array given by b
    36  func (u *U8) UnmarshalJSON(b []byte) error {
    37  	var tmp uint8
    38  	if err := json.Unmarshal(b, &tmp); err != nil {
    39  		return err
    40  	}
    41  	*u = U8(tmp)
    42  	return nil
    43  }
    44  
    45  // MarshalJSON returns a JSON encoded byte array of u
    46  func (u U8) MarshalJSON() ([]byte, error) {
    47  	return json.Marshal(uint8(u))
    48  }
    49  
    50  // U16 is an unsigned 16-bit integer
    51  type U16 uint16
    52  
    53  // NewU16 creates a new U16 type
    54  func NewU16(u uint16) U16 {
    55  	return U16(u)
    56  }
    57  
    58  // UnmarshalJSON fills u with the JSON encoded byte array given by b
    59  func (u *U16) UnmarshalJSON(b []byte) error {
    60  	var tmp uint16
    61  	if err := json.Unmarshal(b, &tmp); err != nil {
    62  		return err
    63  	}
    64  	*u = U16(tmp)
    65  	return nil
    66  }
    67  
    68  // MarshalJSON returns a JSON encoded byte array of u
    69  func (u U16) MarshalJSON() ([]byte, error) {
    70  	return json.Marshal(uint16(u))
    71  }
    72  
    73  // U32 is an unsigned 32-bit integer
    74  type U32 uint32
    75  
    76  // NewU32 creates a new U32 type
    77  func NewU32(u uint32) U32 {
    78  	return U32(u)
    79  }
    80  
    81  // UnmarshalJSON fills u with the JSON encoded byte array given by b
    82  func (u *U32) UnmarshalJSON(b []byte) error {
    83  	var tmp uint32
    84  	if err := json.Unmarshal(b, &tmp); err != nil {
    85  		return err
    86  	}
    87  	*u = U32(tmp)
    88  	return nil
    89  }
    90  
    91  // MarshalJSON returns a JSON encoded byte array of u
    92  func (u U32) MarshalJSON() ([]byte, error) {
    93  	return json.Marshal(uint32(u))
    94  }
    95  
    96  // U64 is an unsigned 64-bit integer
    97  type U64 uint64
    98  
    99  // NewU64 creates a new U64 type
   100  func NewU64(u uint64) U64 {
   101  	return U64(u)
   102  }
   103  
   104  // UnmarshalJSON fills u with the JSON encoded byte array given by b
   105  func (u *U64) UnmarshalJSON(b []byte) error {
   106  	var tmp uint64
   107  	if err := json.Unmarshal(b, &tmp); err != nil {
   108  		return err
   109  	}
   110  	*u = U64(tmp)
   111  	return nil
   112  }
   113  
   114  // MarshalJSON returns a JSON encoded byte array of u
   115  func (u U64) MarshalJSON() ([]byte, error) {
   116  	return json.Marshal(uint64(u))
   117  }
   118  
   119  // U128 is an unsigned 128-bit integer, it is represented as a big.Int in Go.
   120  type U128 struct {
   121  	*big.Int
   122  }
   123  
   124  // NewU128 creates a new U128 type
   125  func NewU128(i big.Int) U128 {
   126  	return U128{&i}
   127  }
   128  
   129  // Decode implements decoding as per the Scale specification
   130  func (i *U128) Decode(decoder scale.Decoder) error {
   131  	bs := make([]byte, 16)
   132  	err := decoder.Read(bs)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	// reverse bytes, scale uses little-endian encoding, big.int's bytes are expected in big-endian
   137  	scale.Reverse(bs)
   138  
   139  	b, err := UintBytesToBigInt(bs)
   140  	if err != nil {
   141  		return err
   142  	}
   143  
   144  	// deal with zero differently to get a nil representation (this is how big.Int deals with 0)
   145  	if b.Sign() == 0 {
   146  		*i = U128{big.NewInt(0)}
   147  		return nil
   148  	}
   149  
   150  	*i = U128{b}
   151  	return nil
   152  }
   153  
   154  // Encode implements encoding as per the Scale specification
   155  func (i U128) Encode(encoder scale.Encoder) error {
   156  	b, err := BigIntToUintBytes(i.Int, 16)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	// reverse bytes, scale uses little-endian encoding, big.int's bytes are expected in big-endian
   162  	scale.Reverse(b)
   163  
   164  	return encoder.Write(b)
   165  }
   166  
   167  // U256 is an usigned 256-bit integer, it is represented as a big.Int in Go.
   168  type U256 struct {
   169  	*big.Int
   170  }
   171  
   172  // NewU256 creates a new U256 type
   173  func NewU256(i big.Int) U256 {
   174  	return U256{&i}
   175  }
   176  
   177  // Decode implements decoding as per the Scale specification
   178  func (i *U256) Decode(decoder scale.Decoder) error {
   179  	bs := make([]byte, 32)
   180  	err := decoder.Read(bs)
   181  	if err != nil {
   182  		return err
   183  	}
   184  	// reverse bytes, scale uses little-endian encoding, big.int's bytes are expected in big-endian
   185  	scale.Reverse(bs)
   186  
   187  	b, err := UintBytesToBigInt(bs)
   188  	if err != nil {
   189  		return err
   190  	}
   191  
   192  	// deal with zero differently to get a nil representation (this is how big.Int deals with 0)
   193  	if b.Sign() == 0 {
   194  		*i = U256{big.NewInt(0)}
   195  		return nil
   196  	}
   197  
   198  	*i = U256{b}
   199  	return nil
   200  }
   201  
   202  // Encode implements encoding as per the Scale specification
   203  func (i U256) Encode(encoder scale.Encoder) error {
   204  	b, err := BigIntToUintBytes(i.Int, 32)
   205  	if err != nil {
   206  		return err
   207  	}
   208  
   209  	// reverse bytes, scale uses little-endian encoding, big.int's bytes are expected in big-endian
   210  	scale.Reverse(b)
   211  
   212  	return encoder.Write(b)
   213  }
   214  
   215  // BigIntToUintBytes encodes the given big.Int to a big endian encoded unsigned integer byte slice of the given byte
   216  // length, returning an error if the given big.Int would be bigger than the maximum number the byte slice of the given
   217  // length could hold
   218  func BigIntToUintBytes(i *big.Int, bytelen int) ([]byte, error) {
   219  	if i.Sign() < 0 {
   220  		return nil, fmt.Errorf("cannot encode a negative big.Int into an unsigned integer")
   221  	}
   222  
   223  	max := big.NewInt(0).Exp(big.NewInt(2), big.NewInt(int64(bytelen*8)), nil)
   224  	if i.CmpAbs(max) > 0 {
   225  		return nil, fmt.Errorf("cannot encode big.Int to []byte: given big.Int exceeds highest number "+
   226  			"%v for an uint with %v bits", max, bytelen*8)
   227  	}
   228  
   229  	res := make([]byte, bytelen)
   230  
   231  	bs := i.Bytes()
   232  	copy(res[len(res)-len(bs):], bs)
   233  	return res, nil
   234  }
   235  
   236  // UintBytesToBigInt decodes the given byte slice containing a big endian encoded unsigned integer to a big.Int
   237  func UintBytesToBigInt(b []byte) (*big.Int, error) {
   238  	if len(b) == 0 {
   239  		return nil, fmt.Errorf("cannot decode an empty byte slice")
   240  	}
   241  
   242  	return big.NewInt(0).SetBytes(b), nil
   243  }