github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/types/int.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  // I8 is a signed 8-bit integer
    28  type I8 int8
    29  
    30  // NewI8 creates a new I8 type
    31  func NewI8(i int8) I8 {
    32  	return I8(i)
    33  }
    34  
    35  // UnmarshalJSON fills i with the JSON encoded byte array given by b
    36  func (i *I8) UnmarshalJSON(b []byte) error {
    37  	var tmp int8
    38  	if err := json.Unmarshal(b, &tmp); err != nil {
    39  		return err
    40  	}
    41  	*i = I8(tmp)
    42  	return nil
    43  }
    44  
    45  // MarshalJSON returns a JSON encoded byte array of i
    46  func (i I8) MarshalJSON() ([]byte, error) {
    47  	return json.Marshal(int8(i))
    48  }
    49  
    50  // I16 is a signed 16-bit integer
    51  type I16 int16
    52  
    53  // NewI16 creates a new I16 type
    54  func NewI16(i int16) I16 {
    55  	return I16(i)
    56  }
    57  
    58  // UnmarshalJSON fills i with the JSON encoded byte array given by b
    59  func (i *I16) UnmarshalJSON(b []byte) error {
    60  	var tmp int16
    61  	if err := json.Unmarshal(b, &tmp); err != nil {
    62  		return err
    63  	}
    64  	*i = I16(tmp)
    65  	return nil
    66  }
    67  
    68  // MarshalJSON returns a JSON encoded byte array of i
    69  func (i I16) MarshalJSON() ([]byte, error) {
    70  	return json.Marshal(int16(i))
    71  }
    72  
    73  // I32 is a signed 32-bit integer
    74  type I32 int32
    75  
    76  // NewI32 creates a new I32 type
    77  func NewI32(i int32) I32 {
    78  	return I32(i)
    79  }
    80  
    81  // UnmarshalJSON fills i with the JSON encoded byte array given by b
    82  func (i *I32) UnmarshalJSON(b []byte) error {
    83  	var tmp int32
    84  	if err := json.Unmarshal(b, &tmp); err != nil {
    85  		return err
    86  	}
    87  	*i = I32(tmp)
    88  	return nil
    89  }
    90  
    91  // MarshalJSON returns a JSON encoded byte array of i
    92  func (i I32) MarshalJSON() ([]byte, error) {
    93  	return json.Marshal(int32(i))
    94  }
    95  
    96  // I64 is a signed 64-bit integer
    97  type I64 int64
    98  
    99  // NewI64 creates a new I64 type
   100  func NewI64(i int64) I64 {
   101  	return I64(i)
   102  }
   103  
   104  // UnmarshalJSON fills i with the JSON encoded byte array given by b
   105  func (i *I64) UnmarshalJSON(b []byte) error {
   106  	var tmp int64
   107  	if err := json.Unmarshal(b, &tmp); err != nil {
   108  		return err
   109  	}
   110  	*i = I64(tmp)
   111  	return nil
   112  }
   113  
   114  // MarshalJSON returns a JSON encoded byte array of i
   115  func (i I64) MarshalJSON() ([]byte, error) {
   116  	return json.Marshal(int64(i))
   117  }
   118  
   119  // I128 is a signed 128-bit integer, it is represented as a big.Int in Go.
   120  type I128 struct {
   121  	*big.Int
   122  }
   123  
   124  // NewI128 creates a new I128 type
   125  func NewI128(i big.Int) I128 {
   126  	return I128{&i}
   127  }
   128  
   129  // Decode implements decoding as per the Scale specification
   130  func (i *I128) 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 := IntBytesToBigInt(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 = I128{big.NewInt(0)}
   147  		return nil
   148  	}
   149  
   150  	*i = I128{b}
   151  	return nil
   152  }
   153  
   154  // Encode implements encoding as per the Scale specification
   155  func (i I128) Encode(encoder scale.Encoder) error {
   156  	b, err := BigIntToIntBytes(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  // I256 is a signed 256-bit integer, it is represented as a big.Int in Go.
   168  type I256 struct {
   169  	*big.Int
   170  }
   171  
   172  // NewI256 creates a new I256 type
   173  func NewI256(i big.Int) I256 {
   174  	return I256{&i}
   175  }
   176  
   177  // Decode implements decoding as per the Scale specification
   178  func (i *I256) 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 := IntBytesToBigInt(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 = I256{big.NewInt(0)}
   195  		return nil
   196  	}
   197  
   198  	*i = I256{b}
   199  	return nil
   200  }
   201  
   202  // Encode implements encoding as per the Scale specification
   203  func (i I256) Encode(encoder scale.Encoder) error {
   204  	b, err := BigIntToIntBytes(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  // BigIntToIntBytes encodes the given big.Int to a big endian encoded signed integer byte slice of the given byte
   216  // length, using a two's complement if the big.Int is negative and returning an error if the given big.Int would be
   217  // bigger than the maximum positive (negative) numbers the byte slice of the given length could hold
   218  func BigIntToIntBytes(i *big.Int, bytelen int) ([]byte, error) {
   219  	res := make([]byte, bytelen)
   220  
   221  	maxNeg := big.NewInt(0).Exp(big.NewInt(2), big.NewInt(int64(bytelen*8-1)), nil)
   222  	maxPos := big.NewInt(0).Sub(maxNeg, big.NewInt(1))
   223  
   224  	if i.Sign() >= 0 {
   225  		if i.CmpAbs(maxPos) > 0 {
   226  			return nil, fmt.Errorf("cannot encode big.Int to []byte: given big.Int exceeds highest positive number "+
   227  				"%v for an int with %v bits", maxPos, bytelen*8)
   228  		}
   229  
   230  		bs := i.Bytes()
   231  		copy(res[len(res)-len(bs):], bs)
   232  		return res, nil
   233  	}
   234  
   235  	// negative, two's complement
   236  
   237  	if i.CmpAbs(maxNeg) > 0 {
   238  		return nil, fmt.Errorf("cannot encode big.Int to []byte: given big.Int exceeds highest negative number -"+
   239  			"%v for an int with %v bits", maxNeg, bytelen*8)
   240  	}
   241  
   242  	i = big.NewInt(0).Add(i, big.NewInt(1))
   243  	bs := i.Bytes()
   244  	copy(res[len(res)-len(bs):], bs)
   245  
   246  	// apply not to every byte
   247  	for j, b := range res {
   248  		res[j] = ^b
   249  	}
   250  
   251  	return res, nil
   252  }
   253  
   254  // IntBytesToBigInt decodes the given byte slice containing a big endian encoded signed integer to a big.Int, using a
   255  // two's complement if the most significant bit is 1
   256  func IntBytesToBigInt(b []byte) (*big.Int, error) {
   257  	if len(b) == 0 {
   258  		return nil, fmt.Errorf("cannot decode an empty byte slice")
   259  	}
   260  
   261  	if b[0]&0x80 == 0x00 {
   262  		// positive
   263  		return big.NewInt(0).SetBytes(b), nil
   264  	}
   265  
   266  	// negative, two's complement
   267  	t := make([]byte, len(b))
   268  	copy(t, b)
   269  
   270  	// apply not to every byte
   271  	for j, b := range b {
   272  		t[j] = ^b
   273  	}
   274  
   275  	res := big.NewInt(0).SetBytes(t)
   276  	res = res.Add(res, big.NewInt(1))
   277  	res = res.Neg(res)
   278  
   279  	return res, nil
   280  }