rlp: add support for boolean encoding/decoding

This commit is contained in:
Péter Szilágyi 2015-08-13 11:12:38 +03:00
parent 0dd6911c62
commit 1d2420323c
4 changed files with 53 additions and 0 deletions

View File

@ -183,6 +183,8 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
return decodeBigIntNoPtr, nil return decodeBigIntNoPtr, nil
case isUint(kind): case isUint(kind):
return decodeUint, nil return decodeUint, nil
case kind == reflect.Bool:
return decodeBool, nil
case kind == reflect.String: case kind == reflect.String:
return decodeString, nil return decodeString, nil
case kind == reflect.Slice || kind == reflect.Array: case kind == reflect.Slice || kind == reflect.Array:
@ -211,6 +213,15 @@ func decodeUint(s *Stream, val reflect.Value) error {
return nil return nil
} }
func decodeBool(s *Stream, val reflect.Value) error {
b, err := s.Bool()
if err != nil {
return wrapStreamError(err, val.Type())
}
val.SetBool(b)
return nil
}
func decodeString(s *Stream, val reflect.Value) error { func decodeString(s *Stream, val reflect.Value) error {
b, err := s.Bytes() b, err := s.Bytes()
if err != nil { if err != nil {
@ -697,6 +708,24 @@ func (s *Stream) uint(maxbits int) (uint64, error) {
} }
} }
// Bool reads an RLP string of up to 1 byte and returns its contents
// as an boolean. If the input does not contain an RLP string, the
// returned error will be ErrExpectedString.
func (s *Stream) Bool() (bool, error) {
num, err := s.uint(8)
if err != nil {
return false, err
}
switch num {
case 0:
return false, nil
case 1:
return true, nil
default:
return false, fmt.Errorf("rlp: invalid boolean value: %d", num)
}
}
// List starts decoding an RLP list. If the input does not contain a // List starts decoding an RLP list. If the input does not contain a
// list, the returned error will be ErrExpectedList. When the list's // list, the returned error will be ErrExpectedList. When the list's
// end has been reached, any Stream operation will return EOL. // end has been reached, any Stream operation will return EOL.

View File

@ -19,6 +19,7 @@ package rlp
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"io" "io"
"math/big" "math/big"
@ -116,6 +117,9 @@ func TestStreamErrors(t *testing.T) {
{"817F", calls{"Uint"}, nil, ErrCanonSize}, {"817F", calls{"Uint"}, nil, ErrCanonSize},
{"8180", calls{"Uint"}, nil, nil}, {"8180", calls{"Uint"}, nil, nil},
// Non-valid boolean
{"02", calls{"Bool"}, nil, errors.New("rlp: invalid boolean value: 2")},
// Size tags must use the smallest possible encoding. // Size tags must use the smallest possible encoding.
// Leading zero bytes in the size tag are also rejected. // Leading zero bytes in the size tag are also rejected.
{"8100", calls{"Uint"}, nil, ErrCanonSize}, {"8100", calls{"Uint"}, nil, ErrCanonSize},
@ -315,6 +319,11 @@ var (
) )
var decodeTests = []decodeTest{ var decodeTests = []decodeTest{
// booleans
{input: "01", ptr: new(bool), value: true},
{input: "80", ptr: new(bool), value: false},
{input: "02", ptr: new(bool), error: "rlp: invalid boolean value: 2"},
// integers // integers
{input: "05", ptr: new(uint32), value: uint32(5)}, {input: "05", ptr: new(uint32), value: uint32(5)},
{input: "80", ptr: new(uint32), value: uint32(0)}, {input: "80", ptr: new(uint32), value: uint32(0)},

View File

@ -361,6 +361,8 @@ func makeWriter(typ reflect.Type) (writer, error) {
return writeBigIntNoPtr, nil return writeBigIntNoPtr, nil
case isUint(kind): case isUint(kind):
return writeUint, nil return writeUint, nil
case kind == reflect.Bool:
return writeBool, nil
case kind == reflect.String: case kind == reflect.String:
return writeString, nil return writeString, nil
case kind == reflect.Slice && isByte(typ.Elem()): case kind == reflect.Slice && isByte(typ.Elem()):
@ -398,6 +400,15 @@ func writeUint(val reflect.Value, w *encbuf) error {
return nil return nil
} }
func writeBool(val reflect.Value, w *encbuf) error {
if val.Bool() {
w.str = append(w.str, 0x01)
} else {
w.str = append(w.str, 0x80)
}
return nil
}
func writeBigIntPtr(val reflect.Value, w *encbuf) error { func writeBigIntPtr(val reflect.Value, w *encbuf) error {
ptr := val.Interface().(*big.Int) ptr := val.Interface().(*big.Int)
if ptr == nil { if ptr == nil {

View File

@ -71,6 +71,10 @@ type encTest struct {
} }
var encTests = []encTest{ var encTests = []encTest{
// booleans
{val: true, output: "01"},
{val: false, output: "80"},
// integers // integers
{val: uint32(0), output: "80"}, {val: uint32(0), output: "80"},
{val: uint32(127), output: "7F"}, {val: uint32(127), output: "7F"},