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 }