From c264cdd0ae59975178a25fae085801ea6ef2438f Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Wed, 21 Dec 2016 20:42:49 +0100 Subject: [PATCH 1/2] Use custom Encoding type Previously base variable were having type `int` which could be confusing as with literal base number (16 for hex). By using custom base variable I hope to make it more clear than it was before. --- multibase.go | 9 +++++---- multibase_test.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/multibase.go b/multibase.go index 2065ca6..239acf8 100644 --- a/multibase.go +++ b/multibase.go @@ -1,14 +1,16 @@ package multibase import ( - "encoding/hex" "encoding/base64" + "encoding/hex" "fmt" b58 "github.com/jbenet/go-base58" b32 "github.com/whyrusleeping/base32" ) +type Encoding int + const ( Base1 = '1' Base2 = '0' @@ -34,7 +36,7 @@ const ( var ErrUnsupportedEncoding = fmt.Errorf("selected encoding not supported") -func Encode(base int, data []byte) (string, error) { +func Encode(base Encoding, data []byte) (string, error) { switch base { case Base16, Base16Upper: return string(Base16) + hex.EncodeToString(data), nil @@ -59,7 +61,7 @@ func Encode(base int, data []byte) (string, error) { } } -func Decode(data string) (int, []byte, error) { +func Decode(data string) (Encoding, []byte, error) { if len(data) == 0 { return 0, nil, fmt.Errorf("cannot decode multibase for zero length string") } @@ -94,4 +96,3 @@ func Decode(data string) (int, []byte, error) { return -1, nil, ErrUnsupportedEncoding } } - diff --git a/multibase_test.go b/multibase_test.go index 5757d6d..a086633 100644 --- a/multibase_test.go +++ b/multibase_test.go @@ -10,7 +10,7 @@ func TestRoundTrip(t *testing.T) { buf := make([]byte, 16) rand.Read(buf) - baseList := []int{ Base16, Base32, Base32hex, Base32pad, Base32hexPad, Base58BTC, Base58Flickr, Base64pad, Base64urlPad } + baseList := []Encoding{Base16, Base32, Base32hex, Base32pad, Base32hexPad, Base58BTC, Base58Flickr, Base64pad, Base64urlPad} for _, base := range baseList { enc, err := Encode(base, buf) From 374a93370a0a8397d37caa4a50b13f85166b5310 Mon Sep 17 00:00:00 2001 From: Wigy Date: Mon, 19 Dec 2016 14:34:26 +0100 Subject: [PATCH 2/2] Implement Identity encoding --- multibase.go | 6 ++++++ multibase_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/multibase.go b/multibase.go index 239acf8..9746737 100644 --- a/multibase.go +++ b/multibase.go @@ -12,6 +12,7 @@ import ( type Encoding int const ( + Identity = 0x00 Base1 = '1' Base2 = '0' Base8 = '7' @@ -38,6 +39,9 @@ var ErrUnsupportedEncoding = fmt.Errorf("selected encoding not supported") func Encode(base Encoding, data []byte) (string, error) { switch base { + case Identity: + // 0x00 inside a string is OK in golang and causes no problems with the length calculation. + return string(Identity) + string(data), nil case Base16, Base16Upper: return string(Base16) + hex.EncodeToString(data), nil case Base32, Base32Upper: @@ -67,6 +71,8 @@ func Decode(data string) (Encoding, []byte, error) { } switch data[0] { + case Identity: + return Identity, []byte(data[1:]), nil case Base16, Base16Upper: bytes, err := hex.DecodeString(data[1:]) return Base16, bytes, err diff --git a/multibase_test.go b/multibase_test.go index a086633..e71f77f 100644 --- a/multibase_test.go +++ b/multibase_test.go @@ -6,11 +6,57 @@ import ( "testing" ) +var sampleBytes = []byte("Decentralize everything!!") +var encodedSamples = map[Encoding]string{ + Identity: string(0x00) + "Decentralize everything!!", + Base16: "f446563656e7472616c697a652065766572797468696e672121", + Base58BTC: "zUXE7GvtEk8XTXs1GF8HSGbVA9FCX9SEBPe", + Base64pad: "MRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ==", + Base64urlPad: "URGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchIQ==", +} + +func testEncode(t *testing.T, encoding Encoding, bytes []byte, expected string) { + actual, err := Encode(encoding, bytes) + if err != nil { + t.Error(err) + return + } + if actual != expected { + t.Errorf("encoding failed for %c (%d), expected: %s, got: %s", encoding, encoding, expected, actual) + } +} + +func testDecode(t *testing.T, expectedEncoding Encoding, expectedBytes []byte, data string) { + actualEncoding, actualBytes, err := Decode(data) + if err != nil { + t.Error(err) + return + } + if actualEncoding != expectedEncoding { + t.Errorf("wrong encoding code, expected: %c (%d), got %c (%d)", expectedEncoding, expectedEncoding, actualEncoding, actualEncoding) + } + if !bytes.Equal(actualBytes, expectedBytes) { + t.Errorf("decoding failed for %c (%d), expected: %v, got %v", actualEncoding, actualEncoding, expectedBytes, actualBytes) + } +} + +func TestEncode(t *testing.T) { + for encoding, data := range encodedSamples { + testEncode(t, encoding, sampleBytes, data) + } +} + +func TestDecode(t *testing.T) { + for encoding, data := range encodedSamples { + testDecode(t, encoding, sampleBytes, data) + } +} + func TestRoundTrip(t *testing.T) { - buf := make([]byte, 16) + buf := make([]byte, 17) rand.Read(buf) - baseList := []Encoding{Base16, Base32, Base32hex, Base32pad, Base32hexPad, Base58BTC, Base58Flickr, Base64pad, Base64urlPad} + baseList := []Encoding{Identity, Base16, Base32, Base32hex, Base32pad, Base32hexPad, Base58BTC, Base58Flickr, Base64pad, Base64urlPad} for _, base := range baseList { enc, err := Encode(base, buf)