github.com/stafiprotocol/go-substrate-rpc-client@v1.4.7/pkg/stafidecoder/primitive.go (about)

     1  package stafi_decoder
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"io"
     7  	"math"
     8  
     9  	"github.com/itering/scale.go/utiles"
    10  	"github.com/shopspring/decimal"
    11  )
    12  
    13  type Compact struct {
    14  	ScaleDecoder
    15  	CompactLength int    `json:"compact_length"`
    16  	CompactBytes  []byte `json:"compact_bytes"`
    17  }
    18  
    19  func (c *Compact) ProcessCompactBytes() []byte {
    20  	compactByte := c.NextBytes(1)
    21  	var byteMod = 0
    22  	if len(compactByte) != 0 {
    23  		byteMod = int(compactByte[0]) % 4
    24  	}
    25  	if byteMod == 0 {
    26  		c.CompactLength = 1
    27  	} else if byteMod == 1 {
    28  		c.CompactLength = 2
    29  	} else if byteMod == 2 {
    30  		c.CompactLength = 4
    31  	} else {
    32  		c.CompactLength = 5 + ((int(compactByte[0]) - 3) / 4)
    33  	}
    34  	if c.CompactLength == 1 {
    35  		c.CompactBytes = compactByte
    36  	} else if utiles.IntInSlice(c.CompactLength, []int{2, 4}) {
    37  		c.CompactBytes = append(compactByte[:], c.NextBytes(c.CompactLength - 1)[:]...)
    38  	} else {
    39  		c.CompactBytes = c.NextBytes(c.CompactLength - 1)
    40  	}
    41  	return c.CompactBytes
    42  }
    43  
    44  func (c *Compact) Process() {
    45  	c.ProcessCompactBytes()
    46  	if c.SubType != "" {
    47  		s := ScaleDecoder{TypeString: c.SubType, Data: ScaleBytes{Data: c.CompactBytes}}
    48  		byteData := s.ProcessAndUpdateData(c.SubType)
    49  		if c.CompactLength <= 4 {
    50  			switch v := byteData.(type) {
    51  			case uint64:
    52  				c.Value = v / 4
    53  			case uint32:
    54  				c.Value = uint64(v / 4)
    55  			case int:
    56  				c.Value = uint64(v / 4)
    57  			case decimal.Decimal:
    58  				c.Value = v.Div(decimal.New(4, 0)).Floor()
    59  			case string:
    60  				c.Value = decimal.RequireFromString(v).Div(decimal.New(4, 0)).Floor()
    61  			default:
    62  				c.Value = byteData
    63  			}
    64  		} else {
    65  			c.Value = byteData
    66  		}
    67  	} else {
    68  		c.Value = c.CompactBytes
    69  	}
    70  }
    71  
    72  type CompactU32 struct {
    73  	Compact
    74  	Reader io.Reader
    75  }
    76  
    77  func (c *CompactU32) Init(data ScaleBytes, option *ScaleDecoderOption) {
    78  	c.TypeString = "Compact<u32>"
    79  	c.ScaleDecoder.Init(data, option)
    80  }
    81  
    82  func (c *CompactU32) Process() {
    83  	c.ProcessCompactBytes()
    84  	buf := &bytes.Buffer{}
    85  	c.Reader = buf
    86  	_, _ = buf.Write(c.CompactBytes)
    87  	b := make([]byte, 8)
    88  	_, _ = c.Reader.Read(b)
    89  	c.Value = int(binary.LittleEndian.Uint64(b))
    90  	if c.CompactLength <= 4 {
    91  		c.Value = int(c.Value.(int)) / 4
    92  	}
    93  
    94  }
    95  
    96  func (c *CompactU32) Encode(value int) ScaleBytes {
    97  	if value <= 63 {
    98  		bs := make([]byte, 4)
    99  		binary.LittleEndian.PutUint32(bs, uint32(value<<2))
   100  		c.Data.Data = bs[0:1]
   101  	} else if value <= 16383 {
   102  		bs := make([]byte, 4)
   103  		binary.LittleEndian.PutUint32(bs, uint32(value<<2)|1)
   104  		c.Data.Data = bs[0:2]
   105  	} else if value <= 1073741823 {
   106  		bs := make([]byte, 4)
   107  		binary.LittleEndian.PutUint32(bs, uint32(value<<2)|2)
   108  		c.Data.Data = bs
   109  	}
   110  	return c.Data
   111  }
   112  
   113  type Option struct {
   114  	ScaleDecoder
   115  }
   116  
   117  func (o *Option) Process() {
   118  	optionType := o.NextBytes(1)
   119  	if o.SubType != "" && utiles.BytesToHex(optionType) != "00" {
   120  		o.Value = o.ProcessAndUpdateData(o.SubType)
   121  	}
   122  }
   123  
   124  type Bytes struct {
   125  	ScaleDecoder
   126  }
   127  
   128  func (b *Bytes) Init(data ScaleBytes, option *ScaleDecoderOption) {
   129  	b.TypeString = "Vec<u8>"
   130  	b.ScaleDecoder.Init(data, option)
   131  }
   132  
   133  func (b *Bytes) Process() {
   134  	length := b.ProcessAndUpdateData("Compact<u32>").(int)
   135  	value := b.NextBytes(length)
   136  	if utiles.IsASCII(value) {
   137  		b.Value = string(value)
   138  	} else {
   139  		b.Value = utiles.BytesToHex(value)
   140  	}
   141  }
   142  
   143  type String struct {
   144  	ScaleDecoder
   145  }
   146  
   147  func (b *String) Process() {
   148  	length := b.ProcessAndUpdateData("Compact<u32>").(int)
   149  	value := b.NextBytes(length)
   150  	if utiles.IsASCII(value) {
   151  		b.Value = string(value)
   152  	} else {
   153  		b.Value = utiles.BytesToHex(value)
   154  	}
   155  }
   156  
   157  type BitVec struct {
   158  	Compact
   159  }
   160  
   161  func (b *BitVec) Process() {
   162  	length := b.ProcessAndUpdateData("Compact<u32>").(int)
   163  	b.Value = b.NextBytes(int(math.Ceil(float64(length) / 8)))
   164  }