Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Base8 Implementation #26

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions base8.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package multibase

import (
"fmt"
"strconv"
)

func octalEncodeToString(src []byte) string {
dst := make([]byte, len(src)*3)
octalEncode(dst, src)
return string(dst)
}

var octalTable = [8]byte{
'0', '1', '2', '3', '4', '5', '6', '7',
}

func octalEncode(dst, src []byte) int {
for i, v := range src {
dst[i*3+2] = octalTable[v&0x7]
v = v >> 3
dst[i*3+1] = octalTable[v&0x7]
v = v >> 3
dst[i*3] = octalTable[v&0x7]
v = v >> 3
}

return len(src) * 3
}

// decodeOctalString takes an octal string and gives byte array of decimals
func decodeOctalString(s string) ([]byte, error) {
data := make([]byte, len(s)/3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'd move this after the length check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if len(s)%3 != 0 {
return nil, fmt.Errorf("cannot decode multibase: %s",
"length should be a multiple of 3")
}

for i, dstIndex := 0, 0; i < len(s); i = i + 3 {
value, err := strconv.ParseInt(s[i:i+3], 8, 16)
if err != nil {
return nil, fmt.Errorf("error while conversion: %s", err)
}

data[dstIndex] = byte(value)
dstIndex++
}

return data, nil
}
1 change: 1 addition & 0 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func EncoderByName(str string) (Encoder, error) {
return Encoder{base}, nil
}

// Encoding returns the Encoder's encoding
func (p Encoder) Encoding() Encoding {
return p.enc
}
Expand Down
8 changes: 8 additions & 0 deletions multibase.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
// specified in standard are left out
var Encodings = map[string]Encoding{
"identity": 0x00,
"base8": '7',
"base16": 'f',
"base16upper": 'F',
"base32": 'b',
Expand All @@ -60,8 +61,10 @@ var Encodings = map[string]Encoding{
"base64urlpad": 'U',
}

// EncodingToStr is the reverse map to get string representation given encoding
var EncodingToStr = map[Encoding]string{
0x00: "identity",
'7': "base8",
'f': "base16",
'F': "base16upper",
'b': "base32",
Expand Down Expand Up @@ -92,6 +95,8 @@ func Encode(base Encoding, data []byte) (string, error) {
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 Base8:
return string(Base8) + octalEncodeToString(data), nil
case Base16:
return string(Base16) + hex.EncodeToString(data), nil
case Base16Upper:
Expand Down Expand Up @@ -141,6 +146,9 @@ func Decode(data string) (Encoding, []byte, error) {
switch enc {
case Identity:
return Identity, []byte(data[1:]), nil
case Base8:
bytes, err := decodeOctalString(data[1:])
return enc, bytes, err
case Base16, Base16Upper:
bytes, err := hex.DecodeString(data[1:])
return enc, bytes, err
Expand Down
16 changes: 10 additions & 6 deletions multibase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package multibase

import (
"bytes"
"fmt"
"math/rand"
"testing"
)
Expand All @@ -24,6 +25,7 @@ func TestMap(t *testing.T) {
var sampleBytes = []byte("Decentralize everything!!!")
var encodedSamples = map[Encoding]string{
Identity: string(0x00) + "Decentralize everything!!!",
Base8: "7104145143145156164162141154151172145040145166145162171164150151156147041041041",
Base16: "f446563656e7472616c697a652065766572797468696e67212121",
Base16Upper: "F446563656E7472616C697A652065766572797468696E67212121",
Base32: "birswgzloorzgc3djpjssazlwmvzhs5dinfxgoijbee",
Expand Down Expand Up @@ -81,8 +83,9 @@ func TestDecode(t *testing.T) {
func TestRoundTrip(t *testing.T) {
buf := make([]byte, 17)
rand.Read(buf)
fmt.Println(buf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best to avoid printf in tests. If you want to log this, please use t.Log.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was by a mistake. Removed now.


baseList := []Encoding{Identity, Base16, Base32, Base32hex, Base32pad, Base32hexPad, Base58BTC, Base58Flickr, Base64pad, Base64urlPad}
baseList := []Encoding{Identity, Base8, Base16, Base32, Base32hex, Base32pad, Base32hexPad, Base58BTC, Base58Flickr, Base64pad, Base64urlPad}

for _, base := range baseList {
enc, err := Encode(base, buf)
Expand All @@ -96,17 +99,17 @@ func TestRoundTrip(t *testing.T) {
}

if e != base {
t.Fatal("got wrong encoding out")
t.Fatal("got wrong encoding output")
}

if !bytes.Equal(buf, out) {
t.Fatal("input wasnt the same as output", buf, out)
t.Fatal("input wasn't the same as output", buf, out)
}
}

_, _, err := Decode("")
if err == nil {
t.Fatal("shouldnt be able to decode empty string")
t.Fatal("shouldn't be able to decode empty string")
}
}

Expand All @@ -117,6 +120,7 @@ func BenchmarkRoundTrip(b *testing.B) {

bases := map[string]Encoding{
"Identity": Identity,
"Base8": Base8,
"Base16": Base16,
"Base16Upper": Base16Upper,
"Base32": Base32,
Expand Down Expand Up @@ -149,11 +153,11 @@ func BenchmarkRoundTrip(b *testing.B) {
}

if e != base {
b.Fatal("got wrong encoding out")
b.Fatal("got wrong encoding output")
}

if !bytes.Equal(buf, out) {
b.Fatal("input wasnt the same as output", buf, out)
b.Fatal("input wasn't the same as output", buf, out)
}
}
})
Expand Down