feat: initial Multibase
This commit is contained in:
parent
3d4fdfb9e3
commit
ee15a298a4
|
@ -0,0 +1,72 @@
|
||||||
|
package cid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"git.lumeweb.com/LumeWeb/libs5-go/internal/bases"
|
||||||
|
"github.com/multiformats/go-multibase"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errMultibaseEncodingNotSupported = errors.New("multibase encoding not supported")
|
||||||
|
errMultibaseDecodeZeroLength = errors.New("cannot decode multibase for zero length string")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Encoder interface {
|
||||||
|
ToBytes() []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type multibaseImpl struct {
|
||||||
|
Multibase
|
||||||
|
encoder Encoder
|
||||||
|
}
|
||||||
|
|
||||||
|
type Multibase interface {
|
||||||
|
ToHex() (string, error)
|
||||||
|
ToBase32() (string, error)
|
||||||
|
ToBase64Url() (string, error)
|
||||||
|
ToBase58() (string, error)
|
||||||
|
ToString() (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Multibase = (*multibaseImpl)(nil)
|
||||||
|
|
||||||
|
func NewMultibase(encoder Encoder) Multibase {
|
||||||
|
return &multibaseImpl{encoder: encoder}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DecodeString(data string) (bytes []byte, err error) {
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, errMultibaseDecodeZeroLength
|
||||||
|
}
|
||||||
|
|
||||||
|
switch data[0] {
|
||||||
|
case 'z', 'f', 'u', 'b':
|
||||||
|
_, bytes, err = multibase.Decode(data)
|
||||||
|
case ':':
|
||||||
|
bytes = []byte(data)
|
||||||
|
default:
|
||||||
|
err = errMultibaseEncodingNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multibaseImpl) ToHex() (string, error) {
|
||||||
|
return bases.ToHex(m.encoder.ToBytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multibaseImpl) ToBase32() (string, error) {
|
||||||
|
return bases.ToBase32(m.encoder.ToBytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multibaseImpl) ToBase64Url() (string, error) {
|
||||||
|
return bases.ToBase64Url(m.encoder.ToBytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multibaseImpl) ToBase58() (string, error) {
|
||||||
|
return bases.ToBase58BTC(m.encoder.ToBytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *multibaseImpl) ToString() (string, error) {
|
||||||
|
return m.ToBase58()
|
||||||
|
}
|
|
@ -0,0 +1,257 @@
|
||||||
|
package cid
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.lumeweb.com/LumeWeb/libs5-go/internal/testdata"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type encoder struct {
|
||||||
|
Multibase
|
||||||
|
data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *encoder) ToBytes() []byte {
|
||||||
|
return e.data
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEncoder(data []byte) encoder {
|
||||||
|
e := &encoder{data: data}
|
||||||
|
m := NewMultibase(e)
|
||||||
|
e.Multibase = m
|
||||||
|
|
||||||
|
return *e
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDecodeString(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
data string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantBytes []byte
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "TestValidMultibase_z",
|
||||||
|
args: args{data: testdata.MediaBase58CID},
|
||||||
|
wantBytes: testdata.MediaCIDBytes, // Adjust this based on the expected output of multibase.Decode("zabc")
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TestValidMultibase_f",
|
||||||
|
args: args{data: testdata.MediaBase16CID},
|
||||||
|
wantBytes: testdata.MediaCIDBytes, // Adjust this based on the expected output of multibase.Decode("fxyz")
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TestValidMultibase_u",
|
||||||
|
args: args{data: testdata.MediaBase64CID},
|
||||||
|
wantBytes: testdata.MediaCIDBytes, // Adjust this based on the expected output of multibase.Decode("uhello")
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TestValidMultibase_b",
|
||||||
|
args: args{data: testdata.MediaBase32CID},
|
||||||
|
wantBytes: testdata.MediaCIDBytes, // Adjust this based on the expected output of multibase.Decode("bworld")
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
/* {
|
||||||
|
name: "TestColonPrefix",
|
||||||
|
args: args{data: ":data"},
|
||||||
|
wantBytes: []byte(":data"),
|
||||||
|
wantErr: false,
|
||||||
|
},*/
|
||||||
|
{
|
||||||
|
name: "TestUnsupportedPrefix",
|
||||||
|
args: args{data: "xunsupported"},
|
||||||
|
wantBytes: nil,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TestEmptyInput",
|
||||||
|
args: args{data: ""},
|
||||||
|
wantBytes: nil,
|
||||||
|
wantErr: true,
|
||||||
|
}, /*
|
||||||
|
{
|
||||||
|
name: "TestColonOnlyInput",
|
||||||
|
args: args{data: ":"},
|
||||||
|
wantBytes: []byte(":"),
|
||||||
|
wantErr: false,
|
||||||
|
},*/
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
gotBytes, err := DecodeString(tt.args.data)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("DecodeString() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(gotBytes, tt.wantBytes) {
|
||||||
|
t.Errorf("DecodeString() gotBytes = %v, want %v", gotBytes, tt.wantBytes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultibase_ToBase32(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
encoder encoder
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Is Raw CID",
|
||||||
|
encoder: newEncoder(testdata.RawCIDBytes),
|
||||||
|
want: testdata.RawBase32CID,
|
||||||
|
wantErr: false,
|
||||||
|
}, {
|
||||||
|
name: "Is Media CID",
|
||||||
|
encoder: newEncoder(testdata.MediaCIDBytes),
|
||||||
|
want: testdata.MediaBase32CID,
|
||||||
|
wantErr: false,
|
||||||
|
}, {
|
||||||
|
name: "Is Resolver CID",
|
||||||
|
encoder: newEncoder(testdata.ResolverCIDBytes),
|
||||||
|
want: testdata.ResolverBase32CID,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := tt.encoder.ToBase32()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ToBase32() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("ToBase32() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultibase_ToBase58(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
encoder encoder
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Is Raw CID",
|
||||||
|
encoder: newEncoder(testdata.RawCIDBytes),
|
||||||
|
want: testdata.RawBase58CID,
|
||||||
|
wantErr: false,
|
||||||
|
}, {
|
||||||
|
name: "Is Media CID",
|
||||||
|
encoder: newEncoder(testdata.MediaCIDBytes),
|
||||||
|
want: testdata.MediaBase58CID,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Is Resolver CID",
|
||||||
|
encoder: newEncoder(testdata.ResolverCIDBytes),
|
||||||
|
want: testdata.ResolverBase58CID,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := tt.encoder.ToBase58()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ToBase58() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("ToBase58() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultibase_ToBase64Url(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
encoder encoder
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Is Raw CID",
|
||||||
|
encoder: newEncoder(testdata.RawCIDBytes),
|
||||||
|
want: testdata.RawBase64CID,
|
||||||
|
wantErr: false,
|
||||||
|
}, {
|
||||||
|
name: "Is Media CID",
|
||||||
|
encoder: newEncoder(testdata.MediaCIDBytes),
|
||||||
|
want: testdata.MediaBase64CID,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Is Resolver CID",
|
||||||
|
encoder: newEncoder(testdata.ResolverCIDBytes),
|
||||||
|
want: testdata.ResolverBase64CID,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := tt.encoder.ToBase64Url()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ToBase64Url() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("ToBase64Url() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultibase_ToHex(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
encoder encoder
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Is Raw CID",
|
||||||
|
encoder: newEncoder(testdata.RawCIDBytes),
|
||||||
|
want: testdata.RawBase16CID,
|
||||||
|
wantErr: false,
|
||||||
|
}, {
|
||||||
|
name: "Is Media CID",
|
||||||
|
encoder: newEncoder(testdata.MediaCIDBytes),
|
||||||
|
want: testdata.MediaBase16CID,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Is Resolver CID",
|
||||||
|
encoder: newEncoder(testdata.ResolverCIDBytes),
|
||||||
|
want: testdata.ResolverBase16CID,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := tt.encoder.ToHex()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ToHex() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("ToHex() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultibase_ToString(t *testing.T) {
|
||||||
|
TestMultibase_ToBase58(t)
|
||||||
|
}
|
Loading…
Reference in New Issue