aboutsummaryrefslogtreecommitdiffstats
path: root/rlp/decode.go
diff options
context:
space:
mode:
Diffstat (limited to 'rlp/decode.go')
-rw-r--r--rlp/decode.go59
1 files changed, 50 insertions, 9 deletions
diff --git a/rlp/decode.go b/rlp/decode.go
index 4462d4be4..1381f5274 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -1,18 +1,18 @@
// Copyright 2014 The go-ethereum Authors
-// This file is part of go-ethereum.
+// This file is part of the go-ethereum library.
//
-// go-ethereum is free software: you can redistribute it and/or modify
+// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// go-ethereum is distributed in the hope that it will be useful,
+// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rlp
@@ -110,9 +110,17 @@ func Decode(r io.Reader, val interface{}) error {
// DecodeBytes parses RLP data from b into val.
// Please see the documentation of Decode for the decoding rules.
+// The input must contain exactly one value and no trailing data.
func DecodeBytes(b []byte, val interface{}) error {
// TODO: this could use a Stream from a pool.
- return NewStream(bytes.NewReader(b), uint64(len(b))).Decode(val)
+ r := bytes.NewReader(b)
+ if err := NewStream(r, uint64(len(b))).Decode(val); err != nil {
+ return err
+ }
+ if r.Len() > 0 {
+ return ErrMoreThanOneValue
+ }
+ return nil
}
type decodeError struct {
@@ -175,6 +183,8 @@ func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) {
return decodeBigIntNoPtr, nil
case isUint(kind):
return decodeUint, nil
+ case kind == reflect.Bool:
+ return decodeBool, nil
case kind == reflect.String:
return decodeString, nil
case kind == reflect.Slice || kind == reflect.Array:
@@ -203,6 +213,15 @@ func decodeUint(s *Stream, val reflect.Value) error {
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 {
b, err := s.Bytes()
if err != nil {
@@ -353,7 +372,7 @@ func decodeByteArray(s *Stream, val reflect.Value) error {
return err
}
// Reject cases where single byte encoding should have been used.
- if size == 1 && slice[0] < 56 {
+ if size == 1 && slice[0] < 128 {
return wrapStreamError(ErrCanonSize, val.Type())
}
case List:
@@ -517,6 +536,10 @@ var (
ErrElemTooLarge = errors.New("rlp: element is larger than containing list")
ErrValueTooLarge = errors.New("rlp: value size exceeds available input length")
+ // This error is reported by DecodeBytes if the slice contains
+ // additional data after the first RLP value.
+ ErrMoreThanOneValue = errors.New("rlp: input contains more than one value")
+
// internal errors
errNotInList = errors.New("rlp: call of ListEnd outside of any list")
errNotAtEOL = errors.New("rlp: call of ListEnd not positioned at EOL")
@@ -611,7 +634,7 @@ func (s *Stream) Bytes() ([]byte, error) {
if err = s.readFull(b); err != nil {
return nil, err
}
- if size == 1 && b[0] < 56 {
+ if size == 1 && b[0] < 128 {
return nil, ErrCanonSize
}
return b, nil
@@ -675,7 +698,7 @@ func (s *Stream) uint(maxbits int) (uint64, error) {
return 0, ErrCanonInt
case err != nil:
return 0, err
- case size > 0 && v < 56:
+ case size > 0 && v < 128:
return 0, ErrCanonSize
default:
return v, nil
@@ -685,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, the returned error will be ErrExpectedList. When the list's
// end has been reached, any Stream operation will return EOL.