github.com/gagliardetto/solana-go@v1.11.0/text/types.go (about)

     1  // Copyright 2020 dfuse Platform Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package text
    16  
    17  import (
    18  	"encoding/base64"
    19  	"encoding/binary"
    20  	"encoding/hex"
    21  	"fmt"
    22  	"math/big"
    23  )
    24  
    25  type SafeString string
    26  
    27  func (ss SafeString) TextEncode(encoder *Encoder, option *Option) error {
    28  	return encoder.ToWriter(string(ss), option.indent, option.fgColor)
    29  }
    30  
    31  type Bool bool
    32  
    33  func (b Bool) TextEncode(encoder *Encoder, option *Option) error {
    34  	return encoder.ToWriter(fmt.Sprintf("%t", bool(b)), option.indent, option.fgColor)
    35  }
    36  
    37  type HexBytes []byte
    38  
    39  func (o HexBytes) TextEncode(encoder *Encoder, option *Option) error {
    40  	return encoder.ToWriter(hex.EncodeToString(o), option.indent, option.fgColor)
    41  }
    42  
    43  type Varint16 int16
    44  
    45  func (o Varint16) TextEncode(encoder *Encoder, option *Option) error {
    46  	return encoder.ToWriter(fmt.Sprintf("%d", int(o)), option.indent, option.fgColor)
    47  }
    48  
    49  type Varuint16 uint16
    50  
    51  func (o Varuint16) TextEncode(encoder *Encoder, option *Option) error {
    52  	return encoder.ToWriter(fmt.Sprintf("%d", int(o)), option.indent, option.fgColor)
    53  
    54  }
    55  
    56  type Varuint32 uint32
    57  
    58  func (o Varuint32) TextEncode(encoder *Encoder, option *Option) error {
    59  	return encoder.ToWriter(fmt.Sprintf("%d", int(o)), option.indent, option.fgColor)
    60  }
    61  
    62  type Varint32 int32
    63  
    64  func (o Varint32) TextEncode(encoder *Encoder, option *Option) error {
    65  	return encoder.ToWriter(fmt.Sprintf("%d", int(o)), option.indent, option.fgColor)
    66  
    67  }
    68  
    69  type JSONFloat64 float64
    70  
    71  func (f JSONFloat64) TextEncode(encoder *Encoder, option *Option) error {
    72  	return encoder.ToWriter(fmt.Sprintf("%f", float64(f)), option.indent, option.fgColor)
    73  }
    74  
    75  type Int64 int64
    76  
    77  func (i Int64) TextEncode(encoder *Encoder, option *Option) error {
    78  	return encoder.ToWriter(fmt.Sprintf("%d", int64(i)), option.indent, option.fgColor)
    79  }
    80  
    81  type Uint64 uint64
    82  
    83  func (i Uint64) TextEncode(encoder *Encoder, option *Option) error {
    84  	return encoder.ToWriter(fmt.Sprintf("%d", uint64(i)), option.indent, option.fgColor)
    85  }
    86  
    87  // uint128
    88  type Uint128 struct {
    89  	Lo uint64
    90  	Hi uint64
    91  }
    92  
    93  func (i Uint128) BigInt() *big.Int {
    94  	buf := make([]byte, 16)
    95  	binary.BigEndian.PutUint64(buf[:], i.Hi)
    96  	binary.BigEndian.PutUint64(buf[8:], i.Lo)
    97  	value := (&big.Int{}).SetBytes(buf)
    98  	return value
    99  }
   100  
   101  func (i Uint128) DecimalString() string {
   102  	return i.BigInt().String()
   103  }
   104  
   105  func (i Uint128) TextEncode(encoder *Encoder, option *Option) error {
   106  	return encoder.ToWriter(i.BigInt().String(), option.indent, option.fgColor)
   107  }
   108  
   109  // Int128
   110  type Int128 Uint128
   111  
   112  func (i Int128) BigInt() *big.Int {
   113  	comp := byte(0x80)
   114  	buf := make([]byte, 16)
   115  	binary.BigEndian.PutUint64(buf[:], i.Hi)
   116  	binary.BigEndian.PutUint64(buf[8:], i.Lo)
   117  
   118  	var value *big.Int
   119  	if (buf[0] & comp) == comp {
   120  		buf = twosComplement(buf)
   121  		value = (&big.Int{}).SetBytes(buf)
   122  		value = value.Neg(value)
   123  	} else {
   124  		value = (&big.Int{}).SetBytes(buf)
   125  	}
   126  	return value
   127  }
   128  
   129  func (i Int128) DecimalString() string {
   130  	return i.BigInt().String()
   131  }
   132  
   133  func (i Int128) TextEncode(encoder *Encoder, option *Option) error {
   134  	return encoder.ToWriter(i.BigInt().String(), option.indent, option.fgColor)
   135  }
   136  
   137  type Float128 Uint128
   138  
   139  func (f Float128) TextEncode(encoder *Encoder, option *Option) error {
   140  	return encoder.ToWriter(Uint128(f).DecimalString(), option.indent, option.fgColor)
   141  }
   142  
   143  // Blob
   144  
   145  // Blob is base64 encoded data
   146  // https://github.com/EOSIO/fc/blob/0e74738e938c2fe0f36c5238dbc549665ddaef82/include/fc/variant.hpp#L47
   147  type Blob string
   148  
   149  // Data returns decoded base64 data
   150  func (b Blob) Data() ([]byte, error) {
   151  	return base64.StdEncoding.DecodeString(string(b))
   152  }
   153  
   154  // String returns the blob as a string
   155  func (b Blob) String() string {
   156  	return string(b)
   157  }
   158  
   159  func twosComplement(v []byte) []byte {
   160  	buf := make([]byte, len(v))
   161  	for i, b := range v {
   162  		buf[i] = b ^ byte(0xff)
   163  	}
   164  	one := big.NewInt(1)
   165  	value := (&big.Int{}).SetBytes(buf)
   166  	return value.Add(value, one).Bytes()
   167  }