added base2 implementation as per RFC
This commit is contained in:
55
base2.go
Normal file
55
base2.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user