From 0f656652e6d76deebcfc7834923adf99eadc050f Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 27 Dec 2013 23:48:44 +0100 Subject: [PATCH] Implemented decoding rlp --- rlp.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- rlp_test.go | 15 ++++++++++++--- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/rlp.go b/rlp.go index cce839095..2ea8ff094 100644 --- a/rlp.go +++ b/rlp.go @@ -1,7 +1,7 @@ package main import ( - _"fmt" + "fmt" "bytes" "math" ) @@ -40,11 +40,53 @@ func FromBin(data []byte) uint64 { return FromBin(data[:len(data)-1]) * 256 + uint64(data[len(data)-1]) } -func Decode(data []byte, pos int) { +func Decode(data []byte, pos int) (interface{}, int) { char := int(data[pos]) + slice := make([]interface{}, 0) switch { case char < 24: + return append(slice, data[pos]), pos + 1 + case char < 56: + b := int(data[pos]) - 23 + return FromBin(data[pos+1 : pos+1+b]), pos + 1 + b + case char < 64: + b := int(data[pos]) - 55 + b2 := int(FromBin(data[pos+1 : pos+1+b])) + return FromBin(data[pos+1+b : pos+1+b+b2]), pos+1+b+b2 + case char < 120: + b := int(data[pos]) - 64 + return data[pos+1:pos+1+b], pos+1+b + case char < 128: + b := int(data[pos]) - 119 + b2 := int(FromBin(data[pos+1 : pos+1+b])) + return data[pos+1+b : pos+1+b+b2], pos+1+b+b2 + case char < 184: + b := int(data[pos]) - 128 + pos++ + for i := 0; i < b; i++ { + var obj interface{} + + obj, pos = Decode(data, pos) + slice = append(slice, obj) + } + return slice, pos + case char < 192: + b := int(data[pos]) - 183 + //b2 := int(FromBin(data[pos+1 : pos+1+b])) (ref imprementation has an unused variable) + pos = pos+1+b + for i := 0; i < b; i++ { + var obj interface{} + + obj, pos = Decode(data, pos) + slice = append(slice, obj) + } + return slice, pos + + default: + panic(fmt.Sprintf("byte not supported: %q", char)) } + + return slice, 0 } func Encode(object interface{}) []byte { @@ -86,10 +128,11 @@ func Encode(object interface{}) []byte { // Inline function for writing the slice header WriteSliceHeader := func(length int) { if length < 56 { - buff.WriteString(string(length + 128)) + buff.WriteByte(byte(length + 128)) } else { b2 := ToBin(uint64(length), 0) - buff.WriteString(string(len(b2) + 183) + b2) + buff.WriteByte(byte(len(b2) + 183)) + buff.WriteString(b2) } } diff --git a/rlp_test.go b/rlp_test.go index 922b70978..c2d5ba263 100644 --- a/rlp_test.go +++ b/rlp_test.go @@ -7,14 +7,23 @@ import ( func TestEncode(t *testing.T) { strRes := "Cdog" - str := string(Encode("dog")) + bytes := Encode("dog") + str := string(bytes) if str != strRes { t.Error(fmt.Sprintf("Expected %q, got %q", strRes, str)) } + dec,_ := Decode(bytes, 0) + fmt.Printf("raw: %v encoded: %q == %v\n", dec, str, "dog") - sliceRes := "\u0083CdogCgodCcat" - slice := string(Encode([]string{"dog", "god", "cat"})) + + sliceRes := "\x83CdogCgodCcat" + strs := []string{"dog", "god", "cat"} + bytes = Encode(strs) + slice := string(bytes) if slice != sliceRes { t.Error(fmt.Sprintf("Expected %q, got %q", sliceRes, slice)) } + + dec,_ = Decode(bytes, 0) + fmt.Printf("raw: %v encoded: %q == %v\n", dec, slice, strs) }