added base2 implementation as per RFC

This commit is contained in:
Gowtham Gopalakrishnan
2019-02-10 16:41:02 +05:30
parent 4cd2fef284
commit 0a49bd57bb
3 changed files with 64 additions and 0 deletions

55
base2.go Normal file
View File

@@ -0,0 +1,55 @@
package multibase
import (
"fmt"
"math"
"strconv"
)
// binaryEncodeToString takes an array of bytes and returns
// multibase binary representation
func binaryEncodeToString(src []byte) string {
dst := make([]byte, len(src)*8)
encodeBinary(dst, src)
return string(dst)
}
// encodeBinary takes the src and dst bytes and converts each
// byte to their binary rep using power reduction method
func encodeBinary(dst []byte, src []byte) {
for i := 0; i < len(src); i++ {
t := src[i]
for j := i * 8; j < (i*8)+8; j++ {
higherPower := math.Pow(2, float64(7-(j%8)))
if float64(t) >= higherPower {
dst[j] = '1'
t = t - byte(higherPower)
} else {
dst[j] = '0'
}
}
}
}
// decodeBinaryString takes multibase binary representation
// and returns a byte array
func decodeBinaryString(s string) ([]byte, error) {
if len(s) % 8 != 0 {
return nil, fmt.Errorf("cannot decode multibase: %s",
"length should be a multiple of 4")
}
data := make([]byte, len(s)/8)
for i, dstIndex := 0, 0; i < len(s); i = i + 8 {
value, err := strconv.ParseInt(s[i:i+8], 2, 0)
if err != nil {
return nil, fmt.Errorf("error while conversion: %s", err)
}
data[dstIndex] = byte(value)
dstIndex++
}
return data, nil
}

View File

@@ -42,6 +42,7 @@ const (
// specified in standard are left out
var Encodings = map[string]Encoding{
"identity": 0x00,
"base2": '0',
"base16": 'f',
"base16upper": 'F',
"base32": 'b',
@@ -62,6 +63,7 @@ var Encodings = map[string]Encoding{
var EncodingToStr = map[Encoding]string{
0x00: "identity",
'0': "base2",
'f': "base16",
'F': "base16upper",
'b': "base32",
@@ -92,6 +94,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 Base2:
return string(Base2) + binaryEncodeToString(data), nil
case Base16:
return string(Base16) + hex.EncodeToString(data), nil
case Base16Upper:
@@ -141,6 +145,9 @@ func Decode(data string) (Encoding, []byte, error) {
switch enc {
case Identity:
return Identity, []byte(data[1:]), nil
case Base2:
bytes, err := decodeBinaryString(data[1:])
return enc, bytes, err
case Base16, Base16Upper:
bytes, err := hex.DecodeString(data[1:])
return enc, bytes, err

View File

@@ -24,6 +24,7 @@ func TestMap(t *testing.T) {
var sampleBytes = []byte("Decentralize everything!!!")
var encodedSamples = map[Encoding]string{
Identity: string(0x00) + "Decentralize everything!!!",
Base2: "00100010001100101011000110110010101101110011101000111001001100001011011000110100101111010011001010010000001100101011101100110010101110010011110010111010001101000011010010110111001100111001000010010000100100001",
Base16: "f446563656e7472616c697a652065766572797468696e67212121",
Base16Upper: "F446563656E7472616C697A652065766572797468696E67212121",
Base32: "birswgzloorzgc3djpjssazlwmvzhs5dinfxgoijbee",
@@ -117,6 +118,7 @@ func BenchmarkRoundTrip(b *testing.B) {
bases := map[string]Encoding{
"Identity": Identity,
"Base2": Base2,
"Base16": Base16,
"Base16Upper": Base16Upper,
"Base32": Base32,