Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

decode.gno

2.34 Kb · 127 lines
  1package rlp
  2
  3// DecodeValue decodes exactly one RLP item.
  4func DecodeValue(b []byte) (Value, error) {
  5	v, rest, err := decodeValue(b, 0)
  6	if err != nil {
  7		return Value{}, err
  8	}
  9
 10	if len(rest) != 0 {
 11		return Value{}, ErrTrailingBytes
 12	}
 13
 14	return v, nil
 15}
 16
 17func split(b []byte) (Kind, []byte, []byte, error) {
 18	k, tagSize, contentSize, err := readKind(b)
 19	if err != nil {
 20		return 0, nil, b, err
 21	}
 22
 23	end := tagSize + contentSize
 24
 25	return k, b[tagSize:end], b[end:], nil
 26}
 27
 28func decodeValue(b []byte, depth int) (Value, []byte, error) {
 29	if depth > maxDecodeDepth {
 30		return Value{}, b, ErrDepthLimit
 31	}
 32
 33	k, content, rest, err := split(b)
 34	if err != nil {
 35		return Value{}, b, err
 36	}
 37
 38	if k != KindList {
 39		return Value{Kind: k, Bytes: content}, rest, nil
 40	}
 41
 42	var items []Value
 43	for len(content) > 0 {
 44		var item Value
 45
 46		item, content, err = decodeValue(content, depth+1)
 47		if err != nil {
 48			return Value{}, b, err
 49		}
 50
 51		items = append(items, item)
 52	}
 53
 54	return Value{Kind: KindList, List: items}, rest, nil
 55}
 56
 57func readKind(b []byte) (Kind, int, int, error) {
 58	if len(b) == 0 {
 59		return 0, 0, 0, ErrUnexpectedEOF
 60	}
 61
 62	prefix := b[0]
 63	switch {
 64	case prefix < 0x80:
 65		return KindByte, 0, 1, nil
 66	case prefix < 0xB8:
 67		size := int(prefix - 0x80)
 68		if size == 1 && len(b) > 1 && b[1] < 0x80 {
 69			return 0, 0, 0, ErrCanonSize
 70		}
 71
 72		if len(b) < 1+size {
 73			return 0, 0, 0, ErrValueTooLarge
 74		}
 75
 76		return KindString, 1, size, nil
 77	case prefix < 0xC0:
 78		return readLongItem(b, int(prefix-0xB7), KindString)
 79	case prefix < 0xF8:
 80		size := int(prefix - 0xC0)
 81		if len(b) < 1+size {
 82			return 0, 0, 0, ErrValueTooLarge
 83		}
 84
 85		return KindList, 1, size, nil
 86	default:
 87		return readLongItem(b, int(prefix-0xF7), KindList)
 88	}
 89}
 90
 91func readLongItem(b []byte, sizeLen int, kind Kind) (Kind, int, int, error) {
 92	size, err := readSize(b[1:], sizeLen)
 93	if err != nil {
 94		return 0, 0, 0, err
 95	}
 96
 97	if size > len(b)-1-sizeLen {
 98		return 0, 0, 0, ErrValueTooLarge
 99	}
100
101	return kind, 1 + sizeLen, size, nil
102}
103
104func readSize(b []byte, sizeLen int) (int, error) {
105	if sizeLen == 0 || sizeLen > 8 || len(b) < sizeLen {
106		return 0, ErrUnexpectedEOF
107	}
108
109	if b[0] == 0 {
110		return 0, ErrCanonSize
111	}
112
113	var size uint64
114	for i := 0; i < sizeLen; i++ {
115		size = (size << 8) | uint64(b[i])
116	}
117
118	if size < 56 {
119		return 0, ErrCanonSize
120	}
121
122	if size > uint64(maxInt) {
123		return 0, ErrValueTooLarge
124	}
125
126	return int(size), nil
127}