MultiBase initial implementation with tests.

This commit is contained in:
cheatfate 2018-12-12 03:52:42 +02:00
parent fc6902dda2
commit 7d60e22782
5 changed files with 752 additions and 4 deletions

View File

@ -13,8 +13,9 @@ requires "nim > 0.18.0",
task test, "Runs the test suite":
exec "nim c -r tests/testvarint"
exec "nim c -r tests/testdaemon"
exec "nim c -r tests/testbase58"
exec "nim c -r tests/testbase32"
exec "nim c -r tests/testmultiaddress"
exec "nim c -r tests/testmultihash"
exec "nim c -r tests/testmultibase"
exec "nim c -r tests/testdaemon"

View File

@ -67,7 +67,8 @@ const
HEXLowerCaseAlphabet* = newAlphabet32("0123456789abcdefghijklmnopqrstuv")
proc encodedLength*(btype: typedesc[Base32Types], length: int): int =
## Return length of BASE32 encoded value for plain length ``length``.
## Return estimated length of BASE32 encoded value for plain length
## ``length``.
let reminder = length mod 5
when btype is Base32NoPadTypes:
result = ((length div 5) * 8) + (((reminder * 8) + 4) div 5)
@ -77,7 +78,7 @@ proc encodedLength*(btype: typedesc[Base32Types], length: int): int =
result += 8
proc decodedLength*(btype: typedesc[Base32Types], length: int): int =
## Return length of decoded value of BASE32 encoded value of length
## Return estimated length of decoded value of BASE32 encoded value of length
## ``length``.
let reminder = length mod 8
result = (length div 8) * 5 + ((reminder * 5) div 8)

View File

@ -48,6 +48,16 @@ const
FlickrAlphabet* = newAlphabet58("123456789abcdefghijkmnopqrstu" &
"vwxyzABCDEFGHJKLMNPQRSTUVWXYZ")
proc encodedLength*(btype: typedesc[Base58C], length: int): int =
## Return estimated length of BASE58 encoded value for plain length
## ``length``.
result = (length * 138) div 100 + 1
proc decodedLength*(btype: typedesc[Base58C], length: int): int =
## Return estimated length of decoded value of BASE58 encoded value of length
## ``length``.
result = length + 4
proc encode*(btype: typedesc[Base58C], inbytes: openarray[byte],
outstr: var openarray[char], outlen: var int): Base58Status =
## Encode array of bytes ``inbytes`` using BASE58 encoding and store
@ -114,7 +124,7 @@ proc encode*(btype: typedesc[Base58C],
else:
result = ""
proc decode*(btype: typedesc[Base58C], instr: string,
proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openarray[T],
outbytes: var openarray[byte], outlen: var int): Base58Status =
## Decode BASE58 string and store array of bytes to ``outbytes``. On success
## ``Base58Status.Success`` will be returned and ``outlen`` will be set

429
libp2p/multibase.nim Normal file
View File

@ -0,0 +1,429 @@
## Nim-Libp2p
## Copyright (c) 2018 Status Research & Development GmbH
## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
## at your option.
## This file may not be copied, modified, or distributed except according to
## those terms.
## This module implements MultiBase.
##
## TODO:
## 1. base64
## 2. base32z
import tables, strutils
import base32, base58
type
MultibaseStatus* {.pure.} = enum
Error, Success, Overrun, Incorrect, BadCodec, NotSupported
MultiBase* = object
MBDecoder = proc(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus {.nimcall.}
MBEncoder = proc(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus {.nimcall.}
MBCodeSize = proc(length: int): int {.nimcall.}
MBCodec = object
code: char
name: string
encr: MBEncoder
decr: proc(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus {.nimcall.}
encl: MBCodeSize
decl: MBCodeSize
MultiBaseError* = object of Exception
proc idd(inbytes: openarray[char], outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
let length = len(inbytes)
if length > len(outbytes):
outlen = length
result = MultibaseStatus.Overrun
else:
copyMem(addr outbytes[0], unsafeAddr inbytes[0], length)
outlen = length
result = MultibaseStatus.Success
proc ide(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
let length = len(inbytes)
if length > len(outbytes):
outlen = length
result = MultibaseStatus.Overrun
else:
copyMem(addr outbytes[0], unsafeAddr inbytes[0], length)
outlen = length
result = MultibaseStatus.Success
proc idel(length: int): int = length
proc iddl(length: int): int = length
proc b16d(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
discard
proc b16e(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
discard
proc b16ud(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
discard
proc b16ue(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
discard
proc b16el(length: int): int = length shl 1
proc b16dl(length: int): int = (length + 1) div 2
proc b32ce(r: Base32Status): MultibaseStatus {.inline.} =
result = MultibaseStatus.Error
if r == Base32Status.Incorrect:
result = MultibaseStatus.Incorrect
elif r == Base32Status.Overrun:
result = MultibaseStatus.Overrun
elif r == Base32Status.Success:
result = MultibaseStatus.Success
proc b58ce(r: Base58Status): MultibaseStatus {.inline.} =
result = MultibaseStatus.Error
if r == Base58Status.Incorrect:
result = MultibaseStatus.Incorrect
elif r == Base58Status.Overrun:
result = MultibaseStatus.Overrun
elif r == Base58Status.Success:
result = MultibaseStatus.Success
proc b32hd(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32Lower.decode(inbytes, outbytes, outlen))
proc b32he(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32Lower.encode(inbytes, outbytes, outlen))
proc b32hud(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32Upper.decode(inbytes, outbytes, outlen))
proc b32hue(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32Upper.encode(inbytes, outbytes, outlen))
proc b32hpd(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32LowerPad.decode(inbytes, outbytes, outlen))
proc b32hpe(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32LowerPad.encode(inbytes, outbytes, outlen))
proc b32hpud(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32UpperPad.decode(inbytes, outbytes, outlen))
proc b32hpue(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(HexBase32UpperPad.encode(inbytes, outbytes, outlen))
proc b32d(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(Base32Lower.decode(inbytes, outbytes, outlen))
proc b32e(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(Base32Lower.encode(inbytes, outbytes, outlen))
proc b32ud(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(Base32Upper.decode(inbytes, outbytes, outlen))
proc b32ue(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(Base32Upper.encode(inbytes, outbytes, outlen))
proc b32pd(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(Base32LowerPad.decode(inbytes, outbytes, outlen))
proc b32pe(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(Base32LowerPad.encode(inbytes, outbytes, outlen))
proc b32pud(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b32ce(Base32UpperPad.decode(inbytes, outbytes, outlen))
proc b32pue(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b32ce(Base32UpperPad.encode(inbytes, outbytes, outlen))
proc b32el(length: int): int = Base32Lower.encodedLength(length)
proc b32dl(length: int): int = Base32Lower.decodedLength(length)
proc b32pel(length: int): int = Base32LowerPad.encodedLength(length)
proc b32pdl(length: int): int = Base32LowerPad.decodedLength(length)
proc b58fd(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b58ce(FLCBase58.decode(inbytes, outbytes, outlen))
proc b58fe(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b58ce(FLCBase58.encode(inbytes, outbytes, outlen))
proc b58bd(inbytes: openarray[char],
outbytes: var openarray[byte],
outlen: var int): MultibaseStatus =
result = b58ce(BTCBase58.decode(inbytes, outbytes, outlen))
proc b58be(inbytes: openarray[byte],
outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
result = b58ce(BTCBase58.encode(inbytes, outbytes, outlen))
proc b58el(length: int): int = Base58.encodedLength(length)
proc b58dl(length: int): int = Base58.decodedLength(length)
const
MultibaseCodecs = [
MBCodec(name: "identity", code: chr(0x00),
decr: idd, encr: ide, decl: iddl, encl: idel
),
MBCodec(name: "base1", code: '1'),
MBCodec(name: "base2", code: '0'),
MBCodec(name: "base8", code: '7'),
MBCodec(name: "base10", code: '9'),
MBCodec(name: "base16", code: 'f',
decr: b16d, encr: b16e, decl: b16dl, encl: b16el
),
MBCodec(name: "base16upper", code: 'F',
decr: b16ud, encr: b16ue, decl: b16dl, encl: b16el
),
MBCodec(name: "base32hex", code: 'v',
decr: b32hd, encr: b32he, decl: b32dl, encl: b32el
),
MBCodec(name: "base32hexupper", code: 'V',
decr: b32hud, encr: b32hue, decl: b32dl, encl: b32el
),
MBCodec(name: "base32hexpad", code: 't',
decr: b32hpd, encr: b32hpe, decl: b32pdl, encl: b32pel
),
MBCodec(name: "base32hexpadupper", code: 'T',
decr: b32hpud, encr: b32hpue, decl: b32pdl, encl: b32pel
),
MBCodec(name: "base32", code: 'b',
decr: b32d, encr: b32e, decl: b32dl, encl: b32el
),
MBCodec(name: "base32upper", code: 'B',
decr: b32ud, encr: b32ue, decl: b32dl, encl: b32el
),
MBCodec(name: "base32pad", code: 'c',
decr: b32pd, encr: b32pe, decl: b32pdl, encl: b32pel
),
MBCodec(name: "base32padupper", code: 'C',
decr: b32pud, encr: b32pue, decl: b32pdl, encl: b32pel
),
MBCodec(name: "base32z", code: 'h'),
MBCodec(name: "base58flickr", code: 'Z',
decr: b58fd, encr: b58fe, decl: b58dl, encl: b58el
),
MBCodec(name: "base58btc", code: 'z',
decr: b58bd, encr: b58be, decl: b58dl, encl: b58el
),
MBCodec(name: "base64", code: 'm'),
MBCodec(name: "base64pad", code: 'M'),
MBCodec(name: "base64url", code: 'u'),
MBCodec(name: "base64urlpad", code: 'U')
]
proc initMultiBaseCodeTable(): Table[char, MBCodec] {.compileTime.} =
result = initTable[char, MBCodec]()
for item in MultibaseCodecs:
result[item.code] = item
proc initMultiBaseNameTable(): Table[string, MBCodec] {.compileTime.} =
result = initTable[string, MBCodec]()
for item in MultibaseCodecs:
result[item.name] = item
const
CodeMultibases = initMultiBaseCodeTable()
NameMultibases = initMultiBaseNameTable()
proc encodedLength*(mbtype: typedesc[MultiBase], encoding: string,
length: int): int =
## Return estimated size of buffer to store MultiBase encoded value with
## encoding ``encoding`` of length ``length``.
##
## Procedure returns ``-1`` if ``encoding`` scheme is not supported or
## not present.
let mb = NameMultibases.getOrDefault(encoding)
if len(mb.name) == 0 or isNil(mb.encl):
result = -1
else:
if length == 0:
result = 1
else:
result = mb.encl(length) + 1
proc decodedLength*(mbtype: typedesc[MultiBase], encoding: char,
length: int): int =
## Return estimated size of buffer to store MultiBase decoded value with
## encoding character ``encoding`` of length ``length``.
let mb = CodeMultibases.getOrDefault(encoding)
if len(mb.name) == 0 or isNil(mb.decl) or length == 0:
result = -1
else:
if length == 1:
result = 0
else:
result = mb.decl(length - 1)
proc encode*(mbtype: typedesc[MultiBase], encoding: string,
inbytes: openarray[byte], outbytes: var openarray[char],
outlen: var int): MultibaseStatus =
## Encode array ``inbytes`` using MultiBase encoding scheme ``encoding`` and
## store encoded value to ``outbytes``.
##
## If ``encoding`` is not supported ``MultiBaseStatus.NotSupported`` will be
## returned.
##
## If ``encoding`` is not correct string, then ``MultBaseStatus.BadCodec``
## will be returned.
##
## If length of ``outbytes`` is not enough to store encoded result, then
## ``MultiBaseStatus.Overrun`` error will be returned and ``outlen`` will be
## set to length required.
##
## On successfull encoding ``MultiBaseStatus.Success`` will be returned and
## ``outlen`` will be set to number of encoded octets (bytes).
let mb = NameMultibases.getOrDefault(encoding)
if len(mb.name) == 0:
return MultibaseStatus.BadCodec
if isNil(mb.encr) or isNil(mb.encl):
return MultibaseStatus.NotSupported
if len(outbytes) > 1:
result = mb.encr(inbytes, outbytes.toOpenArray(1, len(outbytes) - 1),
outlen)
if result == MultiBaseStatus.Overrun:
outlen += 1
elif result == MultiBaseStatus.Success:
outlen += 1
outbytes[0] = mb.code
else:
if len(inbytes) == 0 and len(outbytes) == 1:
result = MultiBaseStatus.Success
outlen = 1
outbytes[0] = mb.code
else:
result = MultiBaseStatus.Overrun
outlen = mb.encl(len(inbytes)) + 1
proc decode*(mbtype: typedesc[MultiBase], inbytes: openarray[char],
outbytes: var openarray[byte], outlen: var int): MultibaseStatus =
## Decode array ``inbytes`` using MultiBase encoding and store decoded value
## to ``outbytes``.
##
## If ``inbytes`` is not correct MultiBase string, then
## ``MultiBaseStatus.BadCodec`` if first character is wrong, or
## ``MultiBaseStatus.Incorrect`` if string has incorrect characters for
## such encoding.
##
## If length of ``outbytes`` is not enough to store decoded result, then
## ``MultiBaseStatus.Overrun`` error will be returned and ``outlen`` will be
## set to length required.
##
## On successfull decoding ``MultiBaseStatus.Success`` will be returned and
## ``outlen`` will be set to number of encoded octets (bytes).
let length = len(inbytes)
if length == 0:
return MultibaseStatus.Incorrect
let mb = CodeMultibases.getOrDefault(inbytes[0])
if len(mb.name) == 0:
return MultibaseStatus.BadCodec
if isNil(mb.decr) or isNil(mb.decl):
return MultibaseStatus.NotSupported
if length == 1:
outlen = 0
result = MultibaseStatus.Success
else:
result = mb.decr(inbytes.toOpenArray(1, length - 1), outbytes, outlen)
proc encode*(mbtype: typedesc[MultiBase], encoding: string,
inbytes: openarray[byte]): string =
## Encode array ``inbytes`` using MultiBase encoding scheme ``encoding`` and
## return encoded string.
let length = len(inbytes)
let mb = NameMultibases.getOrDefault(encoding)
if len(mb.name) == 0:
raise newException(MultiBaseError, "Encoding scheme is incorrect!")
if isNil(mb.encr) or isNil(mb.encl):
raise newException(MultiBaseError, "Encoding scheme is not supported!")
var buffer: string
if length > 0:
buffer = newString(mb.encl(length) + 1)
var outlen = 0
let res = mb.encr(inbytes, buffer.toOpenArray(1, len(buffer) - 1), outlen)
if res != MultiBaseStatus.Success:
raise newException(MultiBaseError, "Encoding error [" & $res & "]")
buffer.setLen(outlen + 1)
buffer[0] = mb.code
else:
buffer = newString(1)
buffer[0] = mb.code
result = buffer
proc decode*(mbtype: typedesc[MultiBase], inbytes: openarray[char]): seq[byte] =
## Decode MultiBase encoded array ``inbytes`` and return decoded sequence of
## bytes.
let length = len(inbytes)
if length == 0:
raise newException(MultiBaseError, "Could not decode zero-length string")
let mb = CodeMultibases.getOrDefault(inbytes[0])
if len(mb.name) == 0:
raise newException(MultiBaseError, "MultiBase scheme is incorrect!")
if isNil(mb.decr) or isNil(mb.decl):
raise newException(MultiBaseError, "MultiBase scheme is not supported!")
if length == 1:
result = newSeq[byte]()
else:
var buffer = newSeq[byte](mb.decl(length - 1))
var outlen = 0
let res = mb.decr(inbytes.toOpenArray(1, length - 1),
buffer, outlen)
if res != MultiBaseStatus.Success:
raise newException(MultiBaseError, "Decoding error [" & $res & "]")
result = buffer
result.setLen(outlen)

307
tests/testmultibase.nim Normal file
View File

@ -0,0 +1,307 @@
import unittest
import ../libp2p/multibase
const GoTestVectors = [
[
"identity",
"\x00Decentralize everything!!!",
"Decentralize everything!!!"
],
# [
# "base16",
# "f446563656e7472616c697a652065766572797468696e67212121",
# "Decentralize everything!!!"
# ],
# [
# "base16upper",
# "F446563656E7472616C697A652065766572797468696E67212121",
# "Decentralize everything!!!"
# ],
[
"base32",
"birswgzloorzgc3djpjssazlwmvzhs5dinfxgoijbee",
"Decentralize everything!!!"
],
[
"base32upper",
"BIRSWGZLOORZGC3DJPJSSAZLWMVZHS5DINFXGOIJBEE",
"Decentralize everything!!!"
],
[
"base32pad",
"cirswgzloorzgc3djpjssazlwmvzhs5dinfxgoijbee======",
"Decentralize everything!!!"
],
[
"base32padupper",
"CIRSWGZLOORZGC3DJPJSSAZLWMVZHS5DINFXGOIJBEE======",
"Decentralize everything!!!"
],
[
"base32hex",
"v8him6pbeehp62r39f9ii0pbmclp7it38d5n6e89144",
"Decentralize everything!!!"
],
[
"base32hexupper",
"V8HIM6PBEEHP62R39F9II0PBMCLP7IT38D5N6E89144",
"Decentralize everything!!!"
],
[
"base32hexpad",
"t8him6pbeehp62r39f9ii0pbmclp7it38d5n6e89144======",
"Decentralize everything!!!"
],
[
"base32hexpadupper",
"T8HIM6PBEEHP62R39F9II0PBMCLP7IT38D5N6E89144======",
"Decentralize everything!!!"
],
[
"base58btc",
"z36UQrhJq9fNDS7DiAHM9YXqDHMPfr4EMArvt",
"Decentralize everything!!!"
],
# [
# "base64",
# "mRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchISE",
# "Decentralize everything!!!"
# ],
# [
# "base64url",
# "uRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchISE",
# "Decentralize everything!!!"
# ],
# [
# "base64pad",
# "MRGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchISE=",
# "Decentralize everything!!!"
# ],
# [
# "base64urlpad",
# "URGVjZW50cmFsaXplIGV2ZXJ5dGhpbmchISE=",
# "Decentralize everything!!!"
# ],
]
suite "MultiBase test suite":
test "Zero-length data encoding/decoding test":
var enc = newString(1)
var dec = newSeq[byte]()
var plain = newSeq[byte]()
var olens: array[21, int]
check:
MultiBase.encodedLength("identity", 0) == 1
MultiBase.decodedLength('\x00', 0) == -1
MultiBase.decodedLength('\x00', 1) == 0
check:
MultiBase.encode("identity", plain) == "\x00"
# MultiBase.encode("base1", plain) == "1"
# MultiBase.encode("base2", plain) == "0"
# MultiBase.encode("base8", plain) == "7"
# MultiBase.encode("base10", plain) == "9"
# MultiBase.encode("base16", plain) == "f"
# MultiBase.encode("base16upper", plain) == "F"
MultiBase.encode("base32hex", plain) == "v"
MultiBase.encode("base32hexupper", plain) == "V"
MultiBase.encode("base32hexpad", plain) == "t"
MultiBase.encode("base32hexpadupper", plain) == "T"
MultiBase.encode("base32", plain) == "b"
MultiBase.encode("base32upper", plain) == "B"
MultiBase.encode("base32pad", plain) == "c"
MultiBase.encode("base32padupper", plain) == "C"
MultiBase.encode("base58btc", plain) == "z"
MultiBase.encode("base58flickr", plain) == "Z"
# MultiBase.encode("base64", plain) == "m"
# MultiBase.encode("base64pad", plain) == "M"
# MultiBase.encode("base64url", plain) == "u"
# MultiBase.encode("base64urlpad", plain) == "U"
check:
len(MultiBase.decode("\x00")) == 0
# len(MultiBase.decode("1")) == 0
# len(MultiBase.decode("0")) == 0
# len(MultiBase.decode("7")) == 0
# len(MultiBase.decode("9")) == 0
# len(MultiBase.decode("f")) == 0
# len(MultiBase.decode("F")) == 0
len(MultiBase.decode("v")) == 0
len(MultiBase.decode("V")) == 0
len(MultiBase.decode("t")) == 0
len(MultiBase.decode("T")) == 0
len(MultiBase.decode("b")) == 0
len(MultiBase.decode("B")) == 0
len(MultiBase.decode("c")) == 0
len(MultiBase.decode("C")) == 0
len(MultiBase.decode("z")) == 0
len(MultiBase.decode("Z")) == 0
# len(MultiBase.decode("m")) == 0
# len(MultiBase.decode("M")) == 0
# len(MultiBase.decode("u")) == 0
# len(MultiBase.decode("U")) == 0
check:
MultiBase.encode("identity", plain, enc,
olens[0]) == MultiBaseStatus.Success
enc == "\x00"
olens[0] == 1
# MultiBase.encode("base1", plain, enc,
# olens[1]) == MultiBaseStatus.Success
# enc == "1"
# olens[1] == 1
# MultiBase.encode("base2", plain, enc,
# olens[2]) == MultiBaseStatus.Success
# enc == "0"
# olens[2] == 1
# MultiBase.encode("base8", plain, enc,
# olens[3]) == MultiBaseStatus.Success
# enc == "7"
# olens[3] == 1
# MultiBase.encode("base10", plain, enc,
# olens[4]) == MultiBaseStatus.Success
# enc == "9"
# olens[4] == 1
# MultiBase.encode("base16", plain, enc,
# olens[5]) == MultiBaseStatus.Success
# enc == "f"
# olens[5] == 1
# MultiBase.encode("base16upper", plain, enc,
# olens[6]) == MultiBaseStatus.Success
# enc == "F"
# olens[6] == 1
MultiBase.encode("base32hex", plain, enc,
olens[7]) == MultiBaseStatus.Success
enc == "v"
olens[7] == 1
MultiBase.encode("base32hexupper", plain, enc,
olens[8]) == MultiBaseStatus.Success
enc == "V"
olens[8] == 1
MultiBase.encode("base32hexpad", plain, enc,
olens[9]) == MultiBaseStatus.Success
enc == "t"
olens[9] == 1
MultiBase.encode("base32hexpadupper", plain, enc,
olens[10]) == MultiBaseStatus.Success
enc == "T"
olens[10] == 1
MultiBase.encode("base32", plain, enc,
olens[11]) == MultiBaseStatus.Success
enc == "b"
olens[11] == 1
MultiBase.encode("base32upper", plain, enc,
olens[12]) == MultiBaseStatus.Success
enc == "B"
olens[12] == 1
MultiBase.encode("base32pad", plain, enc,
olens[13]) == MultiBaseStatus.Success
enc == "c"
olens[13] == 1
MultiBase.encode("base32padupper", plain, enc,
olens[14]) == MultiBaseStatus.Success
enc == "C"
olens[14] == 1
MultiBase.encode("base58btc", plain, enc,
olens[15]) == MultiBaseStatus.Success
enc == "z"
olens[15] == 1
MultiBase.encode("base58flickr", plain, enc,
olens[16]) == MultiBaseStatus.Success
enc == "Z"
olens[16] == 1
check:
MultiBase.decode("", dec, olens[0]) == MultiBaseStatus.Incorrect
MultiBase.decode("\x00", dec, olens[0]) == MultiBaseStatus.Success
olens[0] == 0
# MultiBase.decode("1", dec, olens[1]) == MultiBaseStatus.Success
# olens[1] == 0
# MultiBase.decode("0", dec, olens[2]) == MultiBaseStatus.Success
# olens[2] == 0
# MultiBase.decode("7", dec, olens[3]) == MultiBaseStatus.Success
# olens[3] == 0
# MultiBase.decode("9", dec, olens[4]) == MultiBaseStatus.Success
# olens[4] == 0
# MultiBase.decode("f", dec, olens[5]) == MultiBaseStatus.Success
# olens[5] == 0
# MultiBase.decode("F", dec, olens[6]) == MultiBaseStatus.Success
# olens[6] == 0
MultiBase.decode("v", dec, olens[7]) == MultiBaseStatus.Success
olens[7] == 0
MultiBase.decode("V", dec, olens[8]) == MultiBaseStatus.Success
olens[8] == 0
MultiBase.decode("t", dec, olens[9]) == MultiBaseStatus.Success
olens[9] == 0
MultiBase.decode("T", dec, olens[10]) == MultiBaseStatus.Success
olens[10] == 0
MultiBase.decode("b", dec, olens[11]) == MultiBaseStatus.Success
olens[11] == 0
MultiBase.decode("B", dec, olens[12]) == MultiBaseStatus.Success
olens[12] == 0
MultiBase.decode("c", dec, olens[13]) == MultiBaseStatus.Success
olens[13] == 0
MultiBase.decode("C", dec, olens[14]) == MultiBaseStatus.Success
olens[14] == 0
MultiBase.decode("z", dec, olens[15]) == MultiBaseStatus.Success
olens[15] == 0
MultiBase.decode("Z", dec, olens[16]) == MultiBaseStatus.Success
olens[16] == 0
# MultiBase.decode("m", dec, olens[16]) == MultiBaseStatus.Success
# olens[16] == 0
# MultiBase.decode("M", dec, olens[16]) == MultiBaseStatus.Success
# olens[16] == 0
# MultiBase.decode("u", dec, olens[16]) == MultiBaseStatus.Success
# olens[16] == 0
# MultiBase.decode("U", dec, olens[16]) == MultiBaseStatus.Success
# olens[16] == 0
test "go-multibase test vectors":
for item in GoTestVectors:
let encoding = item[0]
let encoded = item[1]
var expect = item[2]
var bexpect = cast[seq[byte]](expect)
var outlen = 0
check:
MultiBase.encode(encoding, bexpect) == encoded
MultiBase.decode(encoded) == bexpect
let elength = MultiBase.encodedLength(encoding, len(expect))
var ebuffer = newString(elength)
outlen = 0
check:
MultiBase.encode(encoding, bexpect, ebuffer,
outlen) == MultiBaseStatus.Success
ebuffer.setLen(outlen)
check:
encoded == ebuffer
let dlength = MultiBase.decodedLength(encoded[0], len(encoded))
var dbuffer = newSeq[byte](dlength)
outlen = 0
check:
MultiBase.decode(encoded, dbuffer, outlen) == MultiBaseStatus.Success
dbuffer.setLen(outlen)
check:
bexpect == dbuffer
test "Unknown codec test":
var data = @[0x00'u8, 0x01'u8]
var ebuffer = newString(100)
var dbuffer = newSeq[byte](100)
var outlen = 0
check:
MultiBase.encode("unknown", data, ebuffer,
outlen) == MultiBaseStatus.BadCodec
MultiBase.decode("\x01\x00", dbuffer, outlen) == MultiBaseStatus.BadCodec
var r1 = false
var r2 = false
try:
var enc = MultiBase.encode("unknwon", data)
except MultiBaseError:
r1 = true
try:
var dec = MultiBase.decode("\x01\x00")
except MultiBaseError:
r2 = true
check:
r1 == true
r2 == true