github.com/mavryk-network/mvgo@v1.19.9/rpc/utils.go (about)

     1  // Copyright (c) 2020-2022 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc
     3  
     4  package rpc
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"strconv"
    11  )
    12  
    13  // private constants strings
    14  var (
    15  	null = []byte(`null`)
    16  )
    17  
    18  const CONTRACT = "contract"
    19  
    20  // BlockID is an interface to abstract different kinds of block addressing modes
    21  type BlockID interface {
    22  	fmt.Stringer
    23  	Int64() int64
    24  }
    25  
    26  // BlockLevel is a block addressing mode that uses the blocks sequence number a.k.a level
    27  type BlockLevel int64
    28  
    29  func (b BlockLevel) String() string {
    30  	return strconv.FormatInt(int64(b), 10)
    31  }
    32  
    33  func (b BlockLevel) Int64() int64 {
    34  	return int64(b)
    35  }
    36  
    37  // BlockAlias is a block addressing mode that uses a constant string
    38  type BlockAlias string
    39  
    40  const (
    41  	Genesis BlockAlias = "genesis"
    42  	Head    BlockAlias = "head"
    43  )
    44  
    45  func (b BlockAlias) String() string {
    46  	return string(b)
    47  }
    48  
    49  func (b BlockAlias) Int64() int64 {
    50  	if b == Genesis {
    51  		return 0
    52  	}
    53  	return -1
    54  }
    55  
    56  // BlockOffset is a block addressing mode that uses relative addressing from a given
    57  // base block.
    58  type BlockOffset struct {
    59  	Base   BlockID
    60  	Offset int64
    61  }
    62  
    63  func NewBlockOffset(id BlockID, n int64) BlockOffset {
    64  	return BlockOffset{
    65  		Base:   id,
    66  		Offset: n,
    67  	}
    68  }
    69  
    70  func (o BlockOffset) String() string {
    71  	ref := o.Base.String()
    72  	if o.Offset > 0 {
    73  		ref += "+" + strconv.FormatInt(o.Offset, 10)
    74  	} else if o.Offset < 0 {
    75  		ref += "~" + strconv.FormatInt(-o.Offset, 10)
    76  	}
    77  	return ref
    78  }
    79  
    80  func (b BlockOffset) Int64() int64 {
    81  	base := b.Base.Int64()
    82  	if base >= 0 {
    83  		return base + b.Offset
    84  	}
    85  	return -1
    86  }
    87  
    88  func unmarshalMultiTypeJSONArray(data []byte, vals ...interface{}) (err error) {
    89  	dec := json.NewDecoder(bytes.NewBuffer(data))
    90  
    91  	// read open bracket
    92  	_, err = dec.Token()
    93  	if err != nil {
    94  		return
    95  	}
    96  
    97  	// while the array contains values
    98  	var i int
    99  	for dec.More() {
   100  		if i >= len(vals) {
   101  			return fmt.Errorf("short JSON data")
   102  		}
   103  		err = dec.Decode(vals[i])
   104  		if err != nil {
   105  			return
   106  		}
   107  		i++
   108  	}
   109  
   110  	// read closing bracket
   111  	_, err = dec.Token()
   112  	return
   113  }
   114  
   115  func marshalMultiTypeJSONArray(vals ...interface{}) (data []byte, err error) {
   116  	buf := bytes.NewBuffer(nil)
   117  	enc := json.NewEncoder(buf)
   118  	buf.WriteByte('[')
   119  	for i, v := range vals {
   120  		if i > 0 {
   121  			buf.WriteByte(',')
   122  		}
   123  		err = enc.Encode(v)
   124  		if err != nil {
   125  			return
   126  		}
   127  	}
   128  	buf.WriteByte(']')
   129  	data = buf.Bytes()
   130  	return
   131  }
   132  
   133  type Int64orString int64
   134  
   135  func (i *Int64orString) UnmarshalJSON(data []byte) error {
   136  	if len(data) == 0 {
   137  		return nil
   138  	}
   139  	if data[0] == '"' {
   140  		data = data[1 : len(data)-1]
   141  	}
   142  	num, err := strconv.ParseInt(string(data), 10, 64)
   143  	if err != nil {
   144  		return err
   145  	}
   146  	*i = Int64orString(num)
   147  	return nil
   148  }
   149  
   150  func (i Int64orString) MarshalJSON() ([]byte, error) {
   151  	return []byte(strconv.Quote(i.String())), nil
   152  }
   153  
   154  func (i Int64orString) Int64() int64 {
   155  	return int64(i)
   156  }
   157  
   158  func (i Int64orString) Int() int {
   159  	return int(i)
   160  }
   161  
   162  func (i Int64orString) String() string {
   163  	return strconv.FormatInt(int64(i), 10)
   164  }