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 all 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
51 changes: 51 additions & 0 deletions base8.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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) {
if len(s)%3 != 0 {
return nil, fmt.Errorf("cannot decode multibase: %s",
"length should be a multiple of 3")
}

data := make([]byte, len(s)/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
14 changes: 8 additions & 6 deletions multibase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,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 @@ -82,7 +83,7 @@ func TestRoundTrip(t *testing.T) {
buf := make([]byte, 17)
rand.Read(buf)

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 +97,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 +118,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 +151,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