mirror of
https://github.com/vacp2p/nim-libp2p.git
synced 2025-03-02 17:10:44 +00:00
First steps to get Result[T].
This commit is contained in:
parent
dfd824bd03
commit
c9b5af87a0
@ -9,13 +9,15 @@
|
|||||||
|
|
||||||
## This module implements BASE58 encoding and decoding procedures.
|
## This module implements BASE58 encoding and decoding procedures.
|
||||||
## This module supports two variants of BASE58 encoding (Bitcoin and Flickr).
|
## This module supports two variants of BASE58 encoding (Bitcoin and Flickr).
|
||||||
|
import result
|
||||||
|
import errors as e
|
||||||
|
|
||||||
type
|
type
|
||||||
Base58Status* {.pure.} = enum
|
# Base58Status* {.pure.} = enum
|
||||||
Error,
|
# Error,
|
||||||
Success,
|
# Success,
|
||||||
Incorrect,
|
# Incorrect,
|
||||||
Overrun
|
# Overrun
|
||||||
|
|
||||||
Base58Alphabet* = object
|
Base58Alphabet* = object
|
||||||
decode*: array[128, int8]
|
decode*: array[128, int8]
|
||||||
@ -59,13 +61,10 @@ proc decodedLength*(btype: typedesc[Base58C], length: int): int =
|
|||||||
result = length + 4
|
result = length + 4
|
||||||
|
|
||||||
proc encode*(btype: typedesc[Base58C], inbytes: openarray[byte],
|
proc encode*(btype: typedesc[Base58C], inbytes: openarray[byte],
|
||||||
outstr: var openarray[char], outlen: var int): Base58Status =
|
outstr: var openarray[char]): Result[int, e.Error] =
|
||||||
## Encode array of bytes ``inbytes`` using BASE58 encoding and store
|
## Encode array of bytes ``inbytes`` using BASE58 encoding and store
|
||||||
## result to ``outstr``. On success ``Base58Status.Success`` will be returned
|
## result to ``outstr``. On success procedure returns number of characters
|
||||||
## and ``outlen`` will be set to number of characters stored inside of
|
## stored inside ``outstr``.
|
||||||
## ``outstr``. If length of ``outstr`` is not enough then
|
|
||||||
## ``Base58Status.Overrun`` will be returned and ``outlen`` will be set to
|
|
||||||
## number of characters required.
|
|
||||||
when btype is BTCBase58:
|
when btype is BTCBase58:
|
||||||
const alphabet = BTCAlphabet
|
const alphabet = BTCAlphabet
|
||||||
elif btype is FLCBase58:
|
elif btype is FLCBase58:
|
||||||
@ -99,9 +98,8 @@ proc encode*(btype: typedesc[Base58C], inbytes: openarray[byte],
|
|||||||
inc(j)
|
inc(j)
|
||||||
|
|
||||||
let needed = zcount + size - j
|
let needed = zcount + size - j
|
||||||
outlen = needed
|
|
||||||
if len(outstr) < needed:
|
if len(outstr) < needed:
|
||||||
result = Base58Status.Overrun
|
result.err(e.OverrunError)
|
||||||
else:
|
else:
|
||||||
for k in 0..<zcount:
|
for k in 0..<zcount:
|
||||||
outstr[k] = cast[char](alphabet.encode[0])
|
outstr[k] = cast[char](alphabet.encode[0])
|
||||||
@ -110,48 +108,109 @@ proc encode*(btype: typedesc[Base58C], inbytes: openarray[byte],
|
|||||||
outstr[i] = cast[char](alphabet.encode[buffer[j]])
|
outstr[i] = cast[char](alphabet.encode[buffer[j]])
|
||||||
inc(j)
|
inc(j)
|
||||||
inc(i)
|
inc(i)
|
||||||
result = Base58Status.Success
|
result.ok(needed)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# ## result to ``outstr``. On success ``Base58Status.Success`` will be returned
|
||||||
|
# ## and ``outlen`` will be set to number of characters stored inside of
|
||||||
|
# ## ``outstr``. If length of ``outstr`` is not enough then
|
||||||
|
# ## ``Base58Status.Overrun`` will be returned and ``outlen`` will be set to
|
||||||
|
# ## number of characters required.
|
||||||
|
# when btype is BTCBase58:
|
||||||
|
# const alphabet = BTCAlphabet
|
||||||
|
# elif btype is FLCBase58:
|
||||||
|
# const alphabet = FlickrAlphabet
|
||||||
|
|
||||||
|
# let binsz = len(inbytes)
|
||||||
|
# var zcount = 0
|
||||||
|
|
||||||
|
# while zcount < binsz and inbytes[zcount] == 0x00'u8:
|
||||||
|
# inc(zcount)
|
||||||
|
|
||||||
|
# let size = ((binsz - zcount) * 138) div 100 + 1
|
||||||
|
# var buffer = newSeq[uint8](size)
|
||||||
|
|
||||||
|
# var hi = size - 1
|
||||||
|
# var i = zcount
|
||||||
|
# var j = size - 1
|
||||||
|
# while i < binsz:
|
||||||
|
# var carry = uint32(inbytes[i])
|
||||||
|
# j = size - 1
|
||||||
|
# while (j > hi) or (carry != 0'u32):
|
||||||
|
# carry = carry + uint32(256'u32 * buffer[j])
|
||||||
|
# buffer[j] = cast[byte](carry mod 58)
|
||||||
|
# carry = carry div 58
|
||||||
|
# dec(j)
|
||||||
|
# hi = j
|
||||||
|
# inc(i)
|
||||||
|
|
||||||
|
# j = 0
|
||||||
|
# while (j < size) and (buffer[j] == 0x00'u8):
|
||||||
|
# inc(j)
|
||||||
|
|
||||||
|
# let needed = zcount + size - j
|
||||||
|
# outlen = needed
|
||||||
|
# if len(outstr) < needed:
|
||||||
|
# result = Base58Status.Overrun
|
||||||
|
# else:
|
||||||
|
# for k in 0..<zcount:
|
||||||
|
# outstr[k] = cast[char](alphabet.encode[0])
|
||||||
|
# i = zcount
|
||||||
|
# while j < size:
|
||||||
|
# outstr[i] = cast[char](alphabet.encode[buffer[j]])
|
||||||
|
# inc(j)
|
||||||
|
# inc(i)
|
||||||
|
# result = Base58Status.Success
|
||||||
|
|
||||||
|
# proc encode*(btype: typedesc[Base58C],
|
||||||
|
# inbytes: openarray[byte]): string {.inline.} =
|
||||||
|
# ## Encode array of bytes ``inbytes`` using BASE58 encoding and return
|
||||||
|
# ## encoded string.
|
||||||
|
# var size = (len(inbytes) * 138) div 100 + 1
|
||||||
|
# result = newString(size)
|
||||||
|
# if btype.encode(inbytes, result.toOpenArray(0, size - 1),
|
||||||
|
# size) == Base58Status.Success:
|
||||||
|
# result.setLen(size)
|
||||||
|
# else:
|
||||||
|
# result = ""
|
||||||
|
|
||||||
proc encode*(btype: typedesc[Base58C],
|
proc encode*(btype: typedesc[Base58C],
|
||||||
inbytes: openarray[byte]): string {.inline.} =
|
inbytes: openarray[byte]): Result[string, e.Error] {.inline.} =
|
||||||
## Encode array of bytes ``inbytes`` using BASE58 encoding and return
|
## Encode array of bytes ``inbytes`` using BASE58 encoding and return
|
||||||
## encoded string.
|
## encoded string.
|
||||||
var size = (len(inbytes) * 138) div 100 + 1
|
var size = (len(inbytes) * 138) div 100 + 1
|
||||||
result = newString(size)
|
var resstr = newString(size)
|
||||||
if btype.encode(inbytes, result.toOpenArray(0, size - 1),
|
let res = btype.encode(inbytes, resstr.toOpenArray(0, size - 1))
|
||||||
size) == Base58Status.Success:
|
if res.isOk:
|
||||||
result.setLen(size)
|
resstr.setLen(res.get())
|
||||||
|
result.ok(resstr)
|
||||||
else:
|
else:
|
||||||
result = ""
|
result.err(res.error)
|
||||||
|
|
||||||
proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openarray[T],
|
proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openarray[T],
|
||||||
outbytes: var openarray[byte], outlen: var int): Base58Status =
|
outbytes: var openarray[byte]): Result[int, e.Error] =
|
||||||
## Decode BASE58 string and store array of bytes to ``outbytes``. On success
|
## Decode BASE58 encoded string and store result to array of bytes
|
||||||
## ``Base58Status.Success`` will be returned and ``outlen`` will be set
|
## ``outbytes``. On success procedure returns number of bytes stored inside
|
||||||
## to number of bytes stored.
|
## of ``outbytes``.
|
||||||
##
|
##
|
||||||
## Length of ``outbytes`` must be equal or more then ``len(instr) + 4``.
|
## Length of ``outbytes`` must be equal or more then ``len(instr) + 4``.
|
||||||
##
|
|
||||||
## If ``instr`` has characters which are not part of BASE58 alphabet, then
|
|
||||||
## ``Base58Status.Incorrect`` will be returned and ``outlen`` will be set to
|
|
||||||
## ``0``.
|
|
||||||
##
|
|
||||||
## If length of ``outbytes`` is not enough to store decoded bytes, then
|
|
||||||
## ``Base58Status.Overrun`` will be returned and ``outlen`` will be set to
|
|
||||||
## number of bytes required.
|
|
||||||
when btype is BTCBase58:
|
when btype is BTCBase58:
|
||||||
const alphabet = BTCAlphabet
|
const alphabet = BTCAlphabet
|
||||||
elif btype is FLCBase58:
|
elif btype is FLCBase58:
|
||||||
const alphabet = FlickrAlphabet
|
const alphabet = FlickrAlphabet
|
||||||
|
|
||||||
|
var outlen = 0
|
||||||
|
|
||||||
if len(instr) == 0:
|
if len(instr) == 0:
|
||||||
outlen = 0
|
result.ok(0)
|
||||||
return Base58Status.Success
|
return
|
||||||
|
|
||||||
let binsz = len(instr) + 4
|
let binsz = len(instr) + 4
|
||||||
if len(outbytes) < binsz:
|
if len(outbytes) < binsz:
|
||||||
outlen = binsz
|
result.err(e.OverrunError)
|
||||||
return Base58Status.Overrun
|
return
|
||||||
|
|
||||||
var bytesleft = binsz mod 4
|
var bytesleft = binsz mod 4
|
||||||
var zeromask: uint32
|
var zeromask: uint32
|
||||||
@ -167,13 +226,11 @@ proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openarray[T],
|
|||||||
|
|
||||||
for i in zcount..<len(instr):
|
for i in zcount..<len(instr):
|
||||||
if (cast[byte](instr[i]) and 0x80'u8) != 0:
|
if (cast[byte](instr[i]) and 0x80'u8) != 0:
|
||||||
outlen = 0
|
result.err(e.IncorrectEncodingError)
|
||||||
result = Base58Status.Incorrect
|
|
||||||
return
|
return
|
||||||
let ch = alphabet.decode[int8(instr[i])]
|
let ch = alphabet.decode[int8(instr[i])]
|
||||||
if ch == -1:
|
if ch == -1:
|
||||||
outlen = 0
|
result.err(e.IncorrectEncodingError)
|
||||||
result = Base58Status.Incorrect
|
|
||||||
return
|
return
|
||||||
var c = cast[uint32](ch)
|
var c = cast[uint32](ch)
|
||||||
for j in countdown(size - 1, 0):
|
for j in countdown(size - 1, 0):
|
||||||
@ -181,12 +238,10 @@ proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openarray[T],
|
|||||||
c = cast[uint32]((t and 0x3F_0000_0000'u64) shr 32)
|
c = cast[uint32]((t and 0x3F_0000_0000'u64) shr 32)
|
||||||
buffer[j] = cast[uint32](t and 0xFFFF_FFFF'u32)
|
buffer[j] = cast[uint32](t and 0xFFFF_FFFF'u32)
|
||||||
if c != 0:
|
if c != 0:
|
||||||
outlen = 0
|
result.err(e.IncorrectEncodingError)
|
||||||
result = Base58Status.Incorrect
|
|
||||||
return
|
return
|
||||||
if (buffer[0] and zeromask) != 0:
|
if (buffer[0] and zeromask) != 0:
|
||||||
outlen = 0
|
result.err(e.IncorrectEncodingError)
|
||||||
result = Base58Status.Incorrect
|
|
||||||
return
|
return
|
||||||
|
|
||||||
var boffset = 0
|
var boffset = 0
|
||||||
@ -217,7 +272,7 @@ proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openarray[T],
|
|||||||
while m < binsz:
|
while m < binsz:
|
||||||
if outbytes[m] != 0x00:
|
if outbytes[m] != 0x00:
|
||||||
if zcount > m:
|
if zcount > m:
|
||||||
result = Base58Status.Overrun
|
result.err(e.OverrunError)
|
||||||
return
|
return
|
||||||
break
|
break
|
||||||
inc(m)
|
inc(m)
|
||||||
@ -226,14 +281,131 @@ proc decode*[T: byte|char](btype: typedesc[Base58C], instr: openarray[T],
|
|||||||
if m < binsz:
|
if m < binsz:
|
||||||
moveMem(addr outbytes[zcount], addr outbytes[binsz - outlen], outlen)
|
moveMem(addr outbytes[zcount], addr outbytes[binsz - outlen], outlen)
|
||||||
outlen += zcount
|
outlen += zcount
|
||||||
result = Base58Status.Success
|
result.ok(outlen)
|
||||||
|
|
||||||
proc decode*(btype: typedesc[Base58C], instr: string): seq[byte] =
|
# 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
|
||||||
|
# ## to number of bytes stored.
|
||||||
|
# ##
|
||||||
|
# ## Length of ``outbytes`` must be equal or more then ``len(instr) + 4``.
|
||||||
|
# ##
|
||||||
|
# ## If ``instr`` has characters which are not part of BASE58 alphabet, then
|
||||||
|
# ## ``Base58Status.Incorrect`` will be returned and ``outlen`` will be set to
|
||||||
|
# ## ``0``.
|
||||||
|
# ##
|
||||||
|
# ## If length of ``outbytes`` is not enough to store decoded bytes, then
|
||||||
|
# ## ``Base58Status.Overrun`` will be returned and ``outlen`` will be set to
|
||||||
|
# ## number of bytes required.
|
||||||
|
# when btype is BTCBase58:
|
||||||
|
# const alphabet = BTCAlphabet
|
||||||
|
# elif btype is FLCBase58:
|
||||||
|
# const alphabet = FlickrAlphabet
|
||||||
|
|
||||||
|
# if len(instr) == 0:
|
||||||
|
# outlen = 0
|
||||||
|
# return Base58Status.Success
|
||||||
|
|
||||||
|
# let binsz = len(instr) + 4
|
||||||
|
# if len(outbytes) < binsz:
|
||||||
|
# outlen = binsz
|
||||||
|
# return Base58Status.Overrun
|
||||||
|
|
||||||
|
# var bytesleft = binsz mod 4
|
||||||
|
# var zeromask: uint32
|
||||||
|
# if bytesleft != 0:
|
||||||
|
# zeromask = cast[uint32](0xFFFF_FFFF'u32 shl (bytesleft * 8))
|
||||||
|
|
||||||
|
# let size = (binsz + 3) div 4
|
||||||
|
# var buffer = newSeq[uint32](size)
|
||||||
|
|
||||||
|
# var zcount = 0
|
||||||
|
# while zcount < len(instr) and instr[zcount] == cast[char](alphabet.encode[0]):
|
||||||
|
# inc(zcount)
|
||||||
|
|
||||||
|
# for i in zcount..<len(instr):
|
||||||
|
# if (cast[byte](instr[i]) and 0x80'u8) != 0:
|
||||||
|
# outlen = 0
|
||||||
|
# result = Base58Status.Incorrect
|
||||||
|
# return
|
||||||
|
# let ch = alphabet.decode[int8(instr[i])]
|
||||||
|
# if ch == -1:
|
||||||
|
# outlen = 0
|
||||||
|
# result = Base58Status.Incorrect
|
||||||
|
# return
|
||||||
|
# var c = cast[uint32](ch)
|
||||||
|
# for j in countdown(size - 1, 0):
|
||||||
|
# let t = cast[uint64](buffer[j]) * 58 + c
|
||||||
|
# c = cast[uint32]((t and 0x3F_0000_0000'u64) shr 32)
|
||||||
|
# buffer[j] = cast[uint32](t and 0xFFFF_FFFF'u32)
|
||||||
|
# if c != 0:
|
||||||
|
# outlen = 0
|
||||||
|
# result = Base58Status.Incorrect
|
||||||
|
# return
|
||||||
|
# if (buffer[0] and zeromask) != 0:
|
||||||
|
# outlen = 0
|
||||||
|
# result = Base58Status.Incorrect
|
||||||
|
# return
|
||||||
|
|
||||||
|
# var boffset = 0
|
||||||
|
# var joffset = 0
|
||||||
|
# if bytesleft == 3:
|
||||||
|
# outbytes[boffset] = cast[uint8]((buffer[0] and 0xFF_0000'u32) shr 16)
|
||||||
|
# inc(boffset)
|
||||||
|
# bytesleft = 2
|
||||||
|
# if bytesleft == 2:
|
||||||
|
# outbytes[boffset] = cast[uint8]((buffer[0] and 0xFF00'u32) shr 8)
|
||||||
|
# inc(boffset)
|
||||||
|
# bytesleft = 1
|
||||||
|
# if bytesleft == 1:
|
||||||
|
# outbytes[boffset] = cast[uint8]((buffer[0] and 0xFF'u32))
|
||||||
|
# inc(boffset)
|
||||||
|
# joffset = 1
|
||||||
|
|
||||||
|
# while joffset < size:
|
||||||
|
# outbytes[boffset + 0] = cast[byte]((buffer[joffset] shr 0x18) and 0xFF)
|
||||||
|
# outbytes[boffset + 1] = cast[byte]((buffer[joffset] shr 0x10) and 0xFF)
|
||||||
|
# outbytes[boffset + 2] = cast[byte]((buffer[joffset] shr 0x8) and 0xFF)
|
||||||
|
# outbytes[boffset + 3] = cast[byte](buffer[joffset] and 0xFF)
|
||||||
|
# boffset += 4
|
||||||
|
# inc(joffset)
|
||||||
|
|
||||||
|
# outlen = binsz
|
||||||
|
# var m = 0
|
||||||
|
# while m < binsz:
|
||||||
|
# if outbytes[m] != 0x00:
|
||||||
|
# if zcount > m:
|
||||||
|
# result = Base58Status.Overrun
|
||||||
|
# return
|
||||||
|
# break
|
||||||
|
# inc(m)
|
||||||
|
# dec(outlen)
|
||||||
|
|
||||||
|
# if m < binsz:
|
||||||
|
# moveMem(addr outbytes[zcount], addr outbytes[binsz - outlen], outlen)
|
||||||
|
# outlen += zcount
|
||||||
|
# result = Base58Status.Success
|
||||||
|
|
||||||
|
# proc decode*(btype: typedesc[Base58C], instr: string): seq[byte] =
|
||||||
|
# ## Decode BASE58 string ``instr`` and return sequence of bytes as result.
|
||||||
|
# if len(instr) > 0:
|
||||||
|
# var size = len(instr) + 4
|
||||||
|
# result = newSeq[byte](size)
|
||||||
|
# if btype.decode(instr, result, size) == Base58Status.Success:
|
||||||
|
# result.setLen(size)
|
||||||
|
# else:
|
||||||
|
# raise newException(Base58Error, "Incorrect base58 string")
|
||||||
|
|
||||||
|
proc decode*(btype: typedesc[Base58C],
|
||||||
|
instr: string): Result[seq[byte], e.Error] =
|
||||||
## Decode BASE58 string ``instr`` and return sequence of bytes as result.
|
## Decode BASE58 string ``instr`` and return sequence of bytes as result.
|
||||||
if len(instr) > 0:
|
if len(instr) > 0:
|
||||||
var size = len(instr) + 4
|
var size = len(instr) + 4
|
||||||
result = newSeq[byte](size)
|
var resbytes = newSeq[byte](size)
|
||||||
if btype.decode(instr, result, size) == Base58Status.Success:
|
let res = btype.decode(instr, resbytes)
|
||||||
result.setLen(size)
|
if res.isOk:
|
||||||
|
resbytes.setLen(res.value)
|
||||||
|
result.ok(resbytes)
|
||||||
else:
|
else:
|
||||||
raise newException(Base58Error, "Incorrect base58 string")
|
result.err(res.error)
|
||||||
|
33
libp2p/errors.nim
Normal file
33
libp2p/errors.nim
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
## 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.
|
||||||
|
import result
|
||||||
|
export result
|
||||||
|
|
||||||
|
type
|
||||||
|
Error* = enum
|
||||||
|
NoError,
|
||||||
|
GenericError,
|
||||||
|
IncorrectError,
|
||||||
|
OverrunError,
|
||||||
|
OverflowError,
|
||||||
|
IncompleteError,
|
||||||
|
EndOfBufferError,
|
||||||
|
NoSupportError,
|
||||||
|
|
||||||
|
VarintError,
|
||||||
|
IncorrectEncodingError,
|
||||||
|
|
||||||
|
MultiAddressMalformedError,
|
||||||
|
MultiAddressDecodeError,
|
||||||
|
MultiAddressEncodeError,
|
||||||
|
MultiAddressProtocolNotFoundError,
|
||||||
|
MultiAddressProtocolIncorrectError,
|
||||||
|
MultiAddressIncorrectError,
|
||||||
|
MultiAddressNoSupportError,
|
||||||
|
|
@ -14,6 +14,7 @@
|
|||||||
## - LibP2P varint, which is able to encode only 63bits of uint64 number and
|
## - LibP2P varint, which is able to encode only 63bits of uint64 number and
|
||||||
## maximum size of encoded value is 9 octets (bytes).
|
## maximum size of encoded value is 9 octets (bytes).
|
||||||
import bitops
|
import bitops
|
||||||
|
import errors as e
|
||||||
|
|
||||||
type
|
type
|
||||||
VarintStatus* {.pure.} = enum
|
VarintStatus* {.pure.} = enum
|
||||||
@ -37,6 +38,10 @@ type
|
|||||||
SomeUVarint* = PBSomeUVarint | LPSomeUVarint
|
SomeUVarint* = PBSomeUVarint | LPSomeUVarint
|
||||||
VarintError* = object of CatchableError
|
VarintError* = object of CatchableError
|
||||||
|
|
||||||
|
Varint* = object
|
||||||
|
value*: uint64
|
||||||
|
length*: int8
|
||||||
|
|
||||||
proc vsizeof*(x: SomeVarint): int {.inline.} =
|
proc vsizeof*(x: SomeVarint): int {.inline.} =
|
||||||
## Returns number of bytes required to encode integer ``x`` as varint.
|
## Returns number of bytes required to encode integer ``x`` as varint.
|
||||||
if x == cast[type(x)](0):
|
if x == cast[type(x)](0):
|
||||||
@ -44,6 +49,36 @@ proc vsizeof*(x: SomeVarint): int {.inline.} =
|
|||||||
else:
|
else:
|
||||||
result = (fastLog2(x) + 1 + 7 - 1) div 7
|
result = (fastLog2(x) + 1 + 7 - 1) div 7
|
||||||
|
|
||||||
|
proc getUVarint*[T: PB|LP](vt: typedesc[T],
|
||||||
|
pbytes: openarray[byte]): Result[Varint, e.Error] =
|
||||||
|
when vt is PB:
|
||||||
|
const MaxBits = 64'u8
|
||||||
|
else:
|
||||||
|
const MaxBits = 63'u8
|
||||||
|
|
||||||
|
var status = e.IncompleteError
|
||||||
|
var shift = 0'u8
|
||||||
|
var outlen = 0'i8
|
||||||
|
var outval = 0'u64
|
||||||
|
|
||||||
|
for i in 0..<len(pbytes):
|
||||||
|
let b = pbytes[i]
|
||||||
|
if shift >= MaxBits:
|
||||||
|
status = e.OverflowError
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
outval = outval or (cast[type(outval)](b and 0x7F'u8) shl shift)
|
||||||
|
shift += 7
|
||||||
|
inc(outlen)
|
||||||
|
if (b and 0x80'u8) == 0'u8:
|
||||||
|
status = e.NoError
|
||||||
|
break
|
||||||
|
|
||||||
|
if status == e.NoError:
|
||||||
|
result.ok(Varint(value: outval, length: outlen))
|
||||||
|
else:
|
||||||
|
result.err(status)
|
||||||
|
|
||||||
proc getUVarint*[T: PB|LP](vtype: typedesc[T],
|
proc getUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
pbytes: openarray[byte],
|
pbytes: openarray[byte],
|
||||||
outlen: var int,
|
outlen: var int,
|
||||||
@ -99,6 +134,34 @@ proc getUVarint*[T: PB|LP](vtype: typedesc[T],
|
|||||||
outlen = 0
|
outlen = 0
|
||||||
outval = cast[type(outval)](0)
|
outval = cast[type(outval)](0)
|
||||||
|
|
||||||
|
proc putUVarint*[T: PB|LP](vt: typedesc[T], pbytes: var openarray[byte],
|
||||||
|
value: SomeUVarint): Result[int, e.Error] =
|
||||||
|
## Returns number of bytes used to encode value ``value``.
|
||||||
|
var buffer: array[10, byte]
|
||||||
|
var k = 0
|
||||||
|
var v = value
|
||||||
|
|
||||||
|
when vt is LP:
|
||||||
|
if sizeof(value) == 8 and (value and 0x8000_0000_0000_0000'u64) != 0'u64:
|
||||||
|
result.err(e.OverflowError)
|
||||||
|
return
|
||||||
|
|
||||||
|
if v <= cast[type(value)](0x7F):
|
||||||
|
buffer[0] = cast[byte](value and 0xFF)
|
||||||
|
inc(k)
|
||||||
|
else:
|
||||||
|
while v != cast[type(value)](0):
|
||||||
|
buffer[k] = cast[byte]((v and 0x7F) or 0x80)
|
||||||
|
v = v shr 7
|
||||||
|
inc(k)
|
||||||
|
buffer[k - 1] = buffer[k - 1] and 0x7F'u8
|
||||||
|
|
||||||
|
if len(pbytes) >= k:
|
||||||
|
copyMem(addr pbytes[0], addr buffer[0], k)
|
||||||
|
result.ok(k)
|
||||||
|
else:
|
||||||
|
result.err(e.OverrunError)
|
||||||
|
|
||||||
proc putUVarint*[T: PB|LP](vtype: typedesc[T],
|
proc putUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
pbytes: var openarray[byte],
|
pbytes: var openarray[byte],
|
||||||
outlen: var int,
|
outlen: var int,
|
||||||
@ -146,6 +209,19 @@ proc putUVarint*[T: PB|LP](vtype: typedesc[T],
|
|||||||
else:
|
else:
|
||||||
result = VarintStatus.Overrun
|
result = VarintStatus.Overrun
|
||||||
|
|
||||||
|
proc getSVarint*(vt: typedesc[PB],
|
||||||
|
pbytes: openarray[byte]): Result[Varint, e.Error] {.inline.} =
|
||||||
|
let res = PB.getUVarint(pbytes)
|
||||||
|
if res.isErr():
|
||||||
|
result.err(res.error)
|
||||||
|
else:
|
||||||
|
var value = res.value.value
|
||||||
|
if (value and 1'u64) != 0'u64:
|
||||||
|
value = not(value shr 1)
|
||||||
|
else:
|
||||||
|
value = value shr 1
|
||||||
|
result.ok(Varint(value: value, length: res.value.length))
|
||||||
|
|
||||||
proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
||||||
outval: var PBSomeSVarint): VarintStatus {.inline.} =
|
outval: var PBSomeSVarint): VarintStatus {.inline.} =
|
||||||
## Decode Google ProtoBuf's `signed varint` from buffer ``pbytes`` and store
|
## Decode Google ProtoBuf's `signed varint` from buffer ``pbytes`` and store
|
||||||
@ -176,6 +252,22 @@ proc getSVarint*(pbytes: openarray[byte], outsize: var int,
|
|||||||
else:
|
else:
|
||||||
outval = cast[type(outval)](value shr 1)
|
outval = cast[type(outval)](value shr 1)
|
||||||
|
|
||||||
|
proc putSVarint*(vt: typedesc[PB], pbytes: var openarray[byte],
|
||||||
|
value: PBSomeSVarint): Result[int, e.Error] {.inline.} =
|
||||||
|
when sizeof(outval) == 8:
|
||||||
|
var v: uint64 =
|
||||||
|
if value < 0:
|
||||||
|
not(cast[uint64](outval) shl 1)
|
||||||
|
else:
|
||||||
|
cast[uint64](outval) shl 1
|
||||||
|
else:
|
||||||
|
var v: uint32 =
|
||||||
|
if outval < 0:
|
||||||
|
not(cast[uint32](outval) shl 1)
|
||||||
|
else:
|
||||||
|
cast[uint32](outval) shl 1
|
||||||
|
result = PB.putUVarint(pbytes, v)
|
||||||
|
|
||||||
proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
||||||
outval: PBSomeSVarint): VarintStatus {.inline.} =
|
outval: PBSomeSVarint): VarintStatus {.inline.} =
|
||||||
## Encode Google ProtoBuf's `signed varint` ``outval`` and store it to array
|
## Encode Google ProtoBuf's `signed varint` ``outval`` and store it to array
|
||||||
@ -204,6 +296,25 @@ proc putSVarint*(pbytes: var openarray[byte], outsize: var int,
|
|||||||
cast[uint32](outval) shl 1
|
cast[uint32](outval) shl 1
|
||||||
result = PB.putUVarint(pbytes, outsize, value)
|
result = PB.putUVarint(pbytes, outsize, value)
|
||||||
|
|
||||||
|
proc encodeVarint*(vt: typedesc[PB],
|
||||||
|
value: PBSomeVarint): Result[seq[byte], e.Error] {.inline.} =
|
||||||
|
var bytes = newSeqOfCap[byte](10)
|
||||||
|
when sizeof(value) == 4:
|
||||||
|
bytes.setLen(5)
|
||||||
|
else:
|
||||||
|
bytes.setLen(10)
|
||||||
|
|
||||||
|
when type(value) is PBSomeSVarint:
|
||||||
|
let res = PB.putSVarint(bytes, value)
|
||||||
|
else:
|
||||||
|
let res = PB.putUVarint(bytes, value)
|
||||||
|
|
||||||
|
if res.isOk:
|
||||||
|
bytes.setLen(res.value.length)
|
||||||
|
result.ok(bytes)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc encodeVarint*(vtype: typedesc[PB],
|
proc encodeVarint*(vtype: typedesc[PB],
|
||||||
value: PBSomeVarint): seq[byte] {.inline.} =
|
value: PBSomeVarint): seq[byte] {.inline.} =
|
||||||
## Encode integer to Google ProtoBuf's `signed/unsigned varint` and returns
|
## Encode integer to Google ProtoBuf's `signed/unsigned varint` and returns
|
||||||
@ -223,6 +334,24 @@ proc encodeVarint*(vtype: typedesc[PB],
|
|||||||
else:
|
else:
|
||||||
raise newException(VarintError, "Error '" & $res & "'")
|
raise newException(VarintError, "Error '" & $res & "'")
|
||||||
|
|
||||||
|
proc encodeVarint*(vt: typedesc[LP],
|
||||||
|
value: LPSomeVarint): Result[seq[byte], e.Error] {.inline.} =
|
||||||
|
when sizeof(value) == 1:
|
||||||
|
var bytes = newSeq[byte](2)
|
||||||
|
elif sizeof(value) == 2:
|
||||||
|
var bytes = newSeq[byte](3)
|
||||||
|
elif sizeof(value) == 4:
|
||||||
|
var bytes = newSeq[byte](5)
|
||||||
|
else:
|
||||||
|
var bytes = newSeq[byte](9)
|
||||||
|
|
||||||
|
let res = LP.putUVarint(bytes, value)
|
||||||
|
if res.isOk:
|
||||||
|
bytes.setLen(res.value.length)
|
||||||
|
result.ok(bytes)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc encodeVarint*(vtype: typedesc[LP],
|
proc encodeVarint*(vtype: typedesc[LP],
|
||||||
value: LPSomeVarint): seq[byte] {.inline.} =
|
value: LPSomeVarint): seq[byte] {.inline.} =
|
||||||
## Encode integer to LibP2P `unsigned varint` and returns sequence of bytes
|
## Encode integer to LibP2P `unsigned varint` and returns sequence of bytes
|
||||||
@ -243,6 +372,13 @@ proc encodeVarint*(vtype: typedesc[LP],
|
|||||||
else:
|
else:
|
||||||
raise newException(VarintError, "Error '" & $res & "'")
|
raise newException(VarintError, "Error '" & $res & "'")
|
||||||
|
|
||||||
|
proc decodeSVarint2*(data: openarray[byte]): Result[int64, e.Error] {.inline.} =
|
||||||
|
let res = PB.getSVarint(data)
|
||||||
|
if res.isOk:
|
||||||
|
result.ok(cast[int64](res.value.value))
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc decodeSVarint*(data: openarray[byte]): int {.inline.} =
|
proc decodeSVarint*(data: openarray[byte]): int {.inline.} =
|
||||||
## Decode signed integer from array ``data`` and return it as result.
|
## Decode signed integer from array ``data`` and return it as result.
|
||||||
var outsize = 0
|
var outsize = 0
|
||||||
@ -250,6 +386,14 @@ proc decodeSVarint*(data: openarray[byte]): int {.inline.} =
|
|||||||
if res != VarintStatus.Success:
|
if res != VarintStatus.Success:
|
||||||
raise newException(VarintError, "Error '" & $res & "'")
|
raise newException(VarintError, "Error '" & $res & "'")
|
||||||
|
|
||||||
|
proc decodeUVarint2*[T: PB|LP](vt: typedesc[T],
|
||||||
|
data: openarray[byte]): Result[uint64, e.Error] {.inline.} =
|
||||||
|
let res = vt.getUVarint(data)
|
||||||
|
if res.isOk:
|
||||||
|
result.ok(res.value.value)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc decodeUVarint*[T: PB|LP](vtype: typedesc[T],
|
proc decodeUVarint*[T: PB|LP](vtype: typedesc[T],
|
||||||
data: openarray[byte]): uint {.inline.} =
|
data: openarray[byte]): uint {.inline.} =
|
||||||
## Decode unsigned integer from array ``data`` and return it as result.
|
## Decode unsigned integer from array ``data`` and return it as result.
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
## those terms.
|
## those terms.
|
||||||
|
|
||||||
## This module implements variable buffer.
|
## This module implements variable buffer.
|
||||||
import varint, strutils
|
import strutils
|
||||||
|
import varint, errors as e
|
||||||
|
|
||||||
type
|
type
|
||||||
VBuffer* = object
|
VBuffer* = object
|
||||||
@ -34,102 +35,184 @@ proc isLiteral[T](s: seq[T]): bool {.inline.} =
|
|||||||
length, reserved: int
|
length, reserved: int
|
||||||
(cast[ptr SeqHeader](s).reserved and (1 shl (sizeof(int) * 8 - 2))) != 0
|
(cast[ptr SeqHeader](s).reserved and (1 shl (sizeof(int) * 8 - 2))) != 0
|
||||||
|
|
||||||
proc initVBuffer*(data: seq[byte], offset = 0): VBuffer =
|
# proc initVBuffer*(data: seq[byte], offset = 0): VBuffer =
|
||||||
## Initialize VBuffer with shallow copy of ``data``.
|
# ## Initialize VBuffer with shallow copy of ``data``.
|
||||||
|
# if isLiteral(data):
|
||||||
|
# result.buffer = data
|
||||||
|
# else:
|
||||||
|
# shallowCopy(result.buffer, data)
|
||||||
|
# result.offset = offset
|
||||||
|
|
||||||
|
# proc initVBuffer*(data: openarray[byte], offset = 0): VBuffer =
|
||||||
|
# ## Initialize VBuffer with copy of ``data``.
|
||||||
|
# result.buffer = newSeq[byte](len(data))
|
||||||
|
# if len(data) > 0:
|
||||||
|
# copyMem(addr result.buffer[0], unsafeAddr data[0], len(data))
|
||||||
|
# result.offset = offset
|
||||||
|
|
||||||
|
# proc initVBuffer*(): VBuffer =
|
||||||
|
# ## Initialize empty VBuffer.
|
||||||
|
# result.buffer = newSeqOfCap[byte](128)
|
||||||
|
|
||||||
|
proc init*(bt: typedesc[VBuffer], data: seq[byte], offset = 0): VBuffer =
|
||||||
|
## Initialize ``VBuffer`` with sequence ``data`` and initial offset
|
||||||
|
## ``offset``.
|
||||||
|
##
|
||||||
|
## If ``data`` is not literal, it will be stored as reference.
|
||||||
if isLiteral(data):
|
if isLiteral(data):
|
||||||
result.buffer = data
|
result.buffer = data
|
||||||
else:
|
else:
|
||||||
shallowCopy(result.buffer, data)
|
shallowCopy(result.buffer, data)
|
||||||
result.offset = offset
|
result.offset = offset
|
||||||
|
|
||||||
proc initVBuffer*(data: openarray[byte], offset = 0): VBuffer =
|
proc init*(bt: typedesc[VBuffer], data: openarray[byte], offset = 0): VBuffer =
|
||||||
## Initialize VBuffer with copy of ``data``.
|
## Initialize ``VBuffer`` with openarray ``data`` and initial offset
|
||||||
result.buffer = newSeq[byte](len(data))
|
## ``offset``.
|
||||||
if len(data) > 0:
|
##
|
||||||
copyMem(addr result.buffer[0], unsafeAddr data[0], len(data))
|
## ``data`` array will be copied to ``VBuffer`` instance.
|
||||||
|
let length = len(data)
|
||||||
|
if length > 0:
|
||||||
|
result.buffer = newSeq[byte](length)
|
||||||
|
copyMem(addr result.buffer[0], unsafeAddr data[0], length)
|
||||||
|
else:
|
||||||
|
result.buffer = newSeq[byte]()
|
||||||
result.offset = offset
|
result.offset = offset
|
||||||
|
|
||||||
proc initVBuffer*(): VBuffer =
|
proc init*(bt: typedesc[VBuffer]): VBuffer =
|
||||||
## Initialize empty VBuffer.
|
## Initialize empty ``VBuffer``.
|
||||||
result.buffer = newSeqOfCap[byte](128)
|
result.buffer = newSeqOfCap[byte](128)
|
||||||
|
result.offset = 0
|
||||||
|
|
||||||
proc writeVarint*(vb: var VBuffer, value: LPSomeUVarint) =
|
# proc writeVarint*(vb: var VBuffer, value: LPSomeUVarint) =
|
||||||
## Write ``value`` as variable unsigned integer.
|
# ## Write ``value`` as variable unsigned integer.
|
||||||
|
# var length = 0
|
||||||
|
# # LibP2P varint supports only 63 bits.
|
||||||
|
# var v = value and cast[type(value)](0x7FFF_FFFF_FFFF_FFFF)
|
||||||
|
# vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
|
||||||
|
# let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
|
||||||
|
# length, v)
|
||||||
|
# doAssert(res == VarintStatus.Success)
|
||||||
|
# vb.offset += length
|
||||||
|
|
||||||
|
proc writeVarint*(vb: var VBuffer,
|
||||||
|
value: LPSomeUVarint): Result[int, e.Error] =
|
||||||
|
## Write ``value`` as variable unsigned integer. Procedure returns number of
|
||||||
|
## bytes written.
|
||||||
var length = 0
|
var length = 0
|
||||||
# LibP2P varint supports only 63 bits.
|
vb.buffer.setLen(len(vb.buffer) + vsizeof(value))
|
||||||
var v = value and cast[type(value)](0x7FFF_FFFF_FFFF_FFFF)
|
|
||||||
vb.buffer.setLen(len(vb.buffer) + vsizeof(v))
|
|
||||||
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
|
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
|
||||||
length, v)
|
value)
|
||||||
doAssert(res == VarintStatus.Success)
|
if res.isOk:
|
||||||
vb.offset += length
|
vb.offset += res.value
|
||||||
|
result.ok(res.value)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc writeSeq*[T: byte|char](vb: var VBuffer, value: openarray[T]) =
|
# proc writeSeq*[T: byte|char](vb: var VBuffer, value: openarray[T]) =
|
||||||
|
# ## Write array ``value`` to buffer ``vb``, value will be prefixed with
|
||||||
|
# ## varint length of the array.
|
||||||
|
# var length = 0
|
||||||
|
# vb.buffer.setLen(len(vb.buffer) + vsizeof(len(value)) + len(value))
|
||||||
|
# let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
|
||||||
|
# length, uint(len(value)))
|
||||||
|
# doAssert(res == VarintStatus.Success)
|
||||||
|
# vb.offset += length
|
||||||
|
# if len(value) > 0:
|
||||||
|
# copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
||||||
|
# vb.offset += len(value)
|
||||||
|
|
||||||
|
proc writeSeq*[T: byte|char](vb: var VBuffer,
|
||||||
|
value: openarray[T]): Result[int, e.Error] =
|
||||||
## Write array ``value`` to buffer ``vb``, value will be prefixed with
|
## Write array ``value`` to buffer ``vb``, value will be prefixed with
|
||||||
## varint length of the array.
|
## varint length of the array. Procedure returns number of bytes written.
|
||||||
var length = 0
|
var length = 0
|
||||||
vb.buffer.setLen(len(vb.buffer) + vsizeof(len(value)) + len(value))
|
vb.buffer.setLen(len(vb.buffer) + vsizeof(len(value)) + len(value))
|
||||||
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
|
let res = LP.putUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
|
||||||
length, uint(len(value)))
|
uint64(len(value)))
|
||||||
doAssert(res == VarintStatus.Success)
|
if res.isOk:
|
||||||
vb.offset += length
|
length = res.value
|
||||||
if len(value) > 0:
|
vb.offset += length
|
||||||
copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
if len(value) > 0:
|
||||||
vb.offset += len(value)
|
copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
||||||
|
length += len(value)
|
||||||
|
vb.offset += len(value)
|
||||||
|
result.ok(length)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc writeArray*[T: byte|char](vb: var VBuffer, value: openarray[T]) =
|
# proc writeArray*[T: byte|char](vb: var VBuffer, value: openarray[T]) =
|
||||||
|
# ## Write array ``value`` to buffer ``vb``, value will NOT be prefixed with
|
||||||
|
# ## varint length of the array.
|
||||||
|
# var length = 0
|
||||||
|
# if len(value) > 0:
|
||||||
|
# vb.buffer.setLen(len(vb.buffer) + len(value))
|
||||||
|
# copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
||||||
|
# vb.offset += len(value)
|
||||||
|
|
||||||
|
proc writeArray*[T: byte|char](vb: var VBuffer,
|
||||||
|
value: openarray[T]): Result[int, e.Error] =
|
||||||
## Write array ``value`` to buffer ``vb``, value will NOT be prefixed with
|
## Write array ``value`` to buffer ``vb``, value will NOT be prefixed with
|
||||||
## varint length of the array.
|
## varint length of the array. Procedure returns number of bytes written.
|
||||||
var length = 0
|
var length = 0
|
||||||
if len(value) > 0:
|
if len(value) > 0:
|
||||||
vb.buffer.setLen(len(vb.buffer) + len(value))
|
vb.buffer.setLen(len(vb.buffer) + len(value))
|
||||||
copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
copyMem(addr vb.buffer[vb.offset], unsafeAddr value[0], len(value))
|
||||||
vb.offset += len(value)
|
vb.offset += len(value)
|
||||||
|
result.ok(len(value))
|
||||||
|
|
||||||
proc finish*(vb: var VBuffer) =
|
proc finish*(vb: var VBuffer) =
|
||||||
## Finishes ``vb``.
|
## Finishes ``vb``.
|
||||||
vb.offset = 0
|
vb.offset = 0
|
||||||
|
|
||||||
proc peekVarint*(vb: var VBuffer, value: var LPSomeUVarint): int =
|
proc peekVarint*(vb: var VBuffer,
|
||||||
|
value: var LPSomeUVarint): Result[int, e.Error] =
|
||||||
## Peek unsigned integer from buffer ``vb`` and store result to ``value``.
|
## Peek unsigned integer from buffer ``vb`` and store result to ``value``.
|
||||||
##
|
##
|
||||||
## This procedure will not adjust internal offset.
|
## This procedure will not adjust internal offset.
|
||||||
##
|
##
|
||||||
## Returns number of bytes peeked from ``vb`` or ``-1`` on error.
|
## Returns number of bytes peeked from ``vb`` or ``-1`` on error.
|
||||||
result = -1
|
if vb.isEmpty():
|
||||||
value = cast[type(value)](0)
|
result.err(e.EndOfBufferError)
|
||||||
var length = 0
|
else:
|
||||||
if not vb.isEmpty():
|
let res = LP.getUVarint(toOpenArray(vb.buffer, vb.offset,
|
||||||
let res = LP.getUVarint(
|
len(vb.buffer) - 1))
|
||||||
toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1), length, value)
|
if res.isOk:
|
||||||
if res == VarintStatus.Success:
|
value = type(value)(res.value.value)
|
||||||
result = length
|
result.ok(res.value.length)
|
||||||
|
else:
|
||||||
|
result.err(e.VarintError)
|
||||||
|
|
||||||
proc peekSeq*[T: string|seq[byte]](vb: var VBuffer, value: var T): int =
|
proc peekSeq*[T: string|seq[byte]](vb: var VBuffer,
|
||||||
|
value: var T): Result[int, e.Error] =
|
||||||
## Peek length prefixed array from buffer ``vb`` and store result to
|
## Peek length prefixed array from buffer ``vb`` and store result to
|
||||||
## ``value``.
|
## ``value``.
|
||||||
##
|
##
|
||||||
## This procedure will not adjust internal offset.
|
## This procedure will not adjust internal offset.
|
||||||
##
|
##
|
||||||
## Returns number of bytes peeked from ``vb`` or ``-1`` on error.
|
## Returns number of bytes peeked from ``vb`` or ``-1`` on error.
|
||||||
result = -1
|
|
||||||
value.setLen(0)
|
value.setLen(0)
|
||||||
var length = 0
|
|
||||||
var size = 0'u64
|
if vb.isEmpty():
|
||||||
if not vb.isEmpty() and
|
result.err(e.EndOfBufferError)
|
||||||
LP.getUVarint(toOpenArray(vb.buffer, vb.offset, len(vb.buffer) - 1),
|
else:
|
||||||
length, size) == VarintStatus.Success:
|
let res = LP.getUVarint(toOpenArray(vb.buffer, vb.offset,
|
||||||
vb.offset += length
|
len(vb.buffer) - 1))
|
||||||
result = length
|
if res.isErr():
|
||||||
if vb.isEnough(int(size)):
|
result.err(e.VarintError)
|
||||||
value.setLen(size)
|
else:
|
||||||
if size > 0'u64:
|
let size = res.value.value
|
||||||
copyMem(addr value[0], addr vb.buffer[vb.offset], size)
|
vb.offset += res.value.length
|
||||||
result += int(size)
|
if vb.isEnough(size):
|
||||||
vb.offset -= length
|
value.setLen(size)
|
||||||
|
if size > 0'u64:
|
||||||
|
copyMem(addr value[0], addr vb.buffer[vb.offset], size)
|
||||||
|
result.ok(res.value.length + size)
|
||||||
|
else:
|
||||||
|
result.err(e.EndOfBufferError)
|
||||||
|
vb.offset -= res.value.length
|
||||||
|
|
||||||
proc peekArray*[T: char|byte](vb: var VBuffer,
|
proc peekArray*[T: char|byte](vb: var VBuffer,
|
||||||
value: var openarray[T]): int =
|
value: var openarray[T]): Result[int, e.Error] =
|
||||||
## Peek array from buffer ``vb`` and store result to ``value``.
|
## Peek array from buffer ``vb`` and store result to ``value``.
|
||||||
##
|
##
|
||||||
## This procedure will not adjust internal offset.
|
## This procedure will not adjust internal offset.
|
||||||
@ -137,37 +220,51 @@ proc peekArray*[T: char|byte](vb: var VBuffer,
|
|||||||
## Returns number of bytes peeked from ``vb`` or ``-1`` on error.
|
## Returns number of bytes peeked from ``vb`` or ``-1`` on error.
|
||||||
result = -1
|
result = -1
|
||||||
let length = len(value)
|
let length = len(value)
|
||||||
if vb.isEnough(length):
|
if length > 0:
|
||||||
if length > 0:
|
if vb.isEnough(length):
|
||||||
copyMem(addr value[0], addr vb.buffer[vb.offset], length)
|
copyMem(addr value[0], addr vb.buffer[vb.offset], length)
|
||||||
result = length
|
result.ok(length)
|
||||||
|
else:
|
||||||
|
result.err(e.EndOfBufferError)
|
||||||
|
else:
|
||||||
|
result.ok(0)
|
||||||
|
|
||||||
proc readVarint*(vb: var VBuffer, value: var LPSomeUVarint): int {.inline.} =
|
proc readVarint*(vb: var VBuffer,
|
||||||
|
value: var LPSomeUVarint): Result[int, e.Error] {.inline.} =
|
||||||
## Read unsigned integer from buffer ``vb`` and store result to ``value``.
|
## Read unsigned integer from buffer ``vb`` and store result to ``value``.
|
||||||
##
|
##
|
||||||
## Returns number of bytes consumed from ``vb`` or ``-1`` on error.
|
## Returns number of bytes consumed from ``vb`` or ``-1`` on error.
|
||||||
result = vb.peekVarint(value)
|
let res = vb.peekVarint(value)
|
||||||
if result != -1:
|
if res.isOk:
|
||||||
vb.offset += result
|
vb.offset += res.value
|
||||||
|
result.ok(res.value)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc readSeq*[T: string|seq[byte]](vb: var VBuffer,
|
proc readSeq*[T: string|seq[byte]](vb: var VBuffer,
|
||||||
value: var T): int {.inline.} =
|
value: var T): Result[int, e.Error] {.inline.} =
|
||||||
## Read length prefixed array from buffer ``vb`` and store result to
|
## Read length prefixed array from buffer ``vb`` and store result to
|
||||||
## ``value``.
|
## ``value``.
|
||||||
##
|
##
|
||||||
## Returns number of bytes consumed from ``vb`` or ``-1`` on error.
|
## Returns number of bytes consumed from ``vb`` or ``-1`` on error.
|
||||||
result = vb.peekSeq(value)
|
let res = vb.peekSeq(value)
|
||||||
if result != -1:
|
if res.isOk:
|
||||||
vb.offset += result
|
vb.offset += res.value
|
||||||
|
result.ok(res.value)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc readArray*[T: char|byte](vb: var VBuffer,
|
proc readArray*[T: char|byte](vb: var VBuffer,
|
||||||
value: var openarray[T]): int {.inline.} =
|
value: var openarray[T]): int {.inline.} =
|
||||||
## Read array from buffer ``vb`` and store result to ``value``.
|
## Read array from buffer ``vb`` and store result to ``value``.
|
||||||
##
|
##
|
||||||
## Returns number of bytes consumed from ``vb`` or ``-1`` on error.
|
## Returns number of bytes consumed from ``vb`` or ``-1`` on error.
|
||||||
result = vb.peekArray(value)
|
let res = vb.peekArray(value)
|
||||||
if result != -1:
|
if res.isOk:
|
||||||
vb.offset += result
|
vb.offset += res.value
|
||||||
|
result.ok(res.value)
|
||||||
|
else:
|
||||||
|
result.err(res.error)
|
||||||
|
|
||||||
proc `$`*(vb: VBuffer): string =
|
proc `$`*(vb: VBuffer): string =
|
||||||
## Return hexadecimal string representation of buffer ``vb``.
|
## Return hexadecimal string representation of buffer ``vb``.
|
||||||
|
@ -55,76 +55,80 @@ const TestVectors = [
|
|||||||
suite "BASE58 encoding test suite":
|
suite "BASE58 encoding test suite":
|
||||||
test "Empty seq/string test":
|
test "Empty seq/string test":
|
||||||
var a = Base58.encode([])
|
var a = Base58.encode([])
|
||||||
check len(a) == 0
|
check:
|
||||||
|
a.isOk == true
|
||||||
|
len(a.value) == 0
|
||||||
var b = Base58.decode("")
|
var b = Base58.decode("")
|
||||||
check len(b) == 0
|
|
||||||
test "Zero test":
|
|
||||||
var s = newString(256)
|
|
||||||
for i in 0..255:
|
|
||||||
s[i] = '1'
|
|
||||||
var buffer: array[256, byte]
|
|
||||||
for i in 0..255:
|
|
||||||
var a = Base58.encode(buffer.toOpenArray(0, i))
|
|
||||||
check a == s[0..i]
|
|
||||||
var b = Base58.decode(a)
|
|
||||||
check b == buffer[0..i]
|
|
||||||
test "Leading zero test":
|
|
||||||
var buffer: array[256, byte]
|
|
||||||
for i in 0..255:
|
|
||||||
buffer[255] = byte(i)
|
|
||||||
var a = Base58.encode(buffer)
|
|
||||||
var b = Base58.decode(a)
|
|
||||||
check:
|
|
||||||
equalMem(addr buffer[0], addr b[0], 256) == true
|
|
||||||
test "Small amount of bytes test":
|
|
||||||
var buffer1: array[1, byte]
|
|
||||||
var buffer2: array[2, byte]
|
|
||||||
for i in 0..255:
|
|
||||||
buffer1[0] = byte(i)
|
|
||||||
var enc = Base58.encode(buffer1)
|
|
||||||
var dec = Base58.decode(enc)
|
|
||||||
check:
|
|
||||||
len(dec) == 1
|
|
||||||
dec[0] == buffer1[0]
|
|
||||||
|
|
||||||
for i in 0..255:
|
|
||||||
for k in 0..255:
|
|
||||||
buffer2[0] = byte(i)
|
|
||||||
buffer2[1] = byte(k)
|
|
||||||
var enc = Base58.encode(buffer2)
|
|
||||||
var dec = Base58.decode(enc)
|
|
||||||
check:
|
|
||||||
len(dec) == 2
|
|
||||||
dec[0] == buffer2[0]
|
|
||||||
dec[1] == buffer2[1]
|
|
||||||
test "Test Vectors test":
|
|
||||||
for item in TestVectors:
|
|
||||||
var a = fromHex(item[0])
|
|
||||||
var enc = Base58.encode(a)
|
|
||||||
var dec = Base58.decode(item[1])
|
|
||||||
check:
|
|
||||||
enc == item[1]
|
|
||||||
dec == a
|
|
||||||
test "Buffer Overrun test":
|
|
||||||
var encres = ""
|
|
||||||
var encsize = 0
|
|
||||||
var decres: seq[byte] = @[]
|
|
||||||
var decsize = 0
|
|
||||||
check:
|
check:
|
||||||
Base58.encode([0'u8], encres, encsize) == Base58Status.Overrun
|
b.isOk == true
|
||||||
encsize == 1
|
len(b.value) == 0
|
||||||
Base58.decode("1", decres, decsize) == Base58Status.Overrun
|
# test "Zero test":
|
||||||
decsize == 5
|
# var s = newString(256)
|
||||||
test "Incorrect test":
|
# for i in 0..255:
|
||||||
var decres = newSeq[byte](10)
|
# s[i] = '1'
|
||||||
var decsize = 0
|
# var buffer: array[256, byte]
|
||||||
check:
|
# for i in 0..255:
|
||||||
Base58.decode("l", decres, decsize) == Base58Status.Incorrect
|
# var a = Base58.encode(buffer.toOpenArray(0, i))
|
||||||
decsize == 0
|
# check a == s[0..i]
|
||||||
Base58.decode("2l", decres, decsize) == Base58Status.Incorrect
|
# var b = Base58.decode(a)
|
||||||
decsize == 0
|
# check b == buffer[0..i]
|
||||||
Base58.decode("O", decres, decsize) == Base58Status.Incorrect
|
# test "Leading zero test":
|
||||||
decsize == 0
|
# var buffer: array[256, byte]
|
||||||
Base58.decode("2O", decres, decsize) == Base58Status.Incorrect
|
# for i in 0..255:
|
||||||
decsize == 0
|
# buffer[255] = byte(i)
|
||||||
|
# var a = Base58.encode(buffer)
|
||||||
|
# var b = Base58.decode(a)
|
||||||
|
# check:
|
||||||
|
# equalMem(addr buffer[0], addr b[0], 256) == true
|
||||||
|
# test "Small amount of bytes test":
|
||||||
|
# var buffer1: array[1, byte]
|
||||||
|
# var buffer2: array[2, byte]
|
||||||
|
# for i in 0..255:
|
||||||
|
# buffer1[0] = byte(i)
|
||||||
|
# var enc = Base58.encode(buffer1)
|
||||||
|
# var dec = Base58.decode(enc)
|
||||||
|
# check:
|
||||||
|
# len(dec) == 1
|
||||||
|
# dec[0] == buffer1[0]
|
||||||
|
|
||||||
|
# for i in 0..255:
|
||||||
|
# for k in 0..255:
|
||||||
|
# buffer2[0] = byte(i)
|
||||||
|
# buffer2[1] = byte(k)
|
||||||
|
# var enc = Base58.encode(buffer2)
|
||||||
|
# var dec = Base58.decode(enc)
|
||||||
|
# check:
|
||||||
|
# len(dec) == 2
|
||||||
|
# dec[0] == buffer2[0]
|
||||||
|
# dec[1] == buffer2[1]
|
||||||
|
# test "Test Vectors test":
|
||||||
|
# for item in TestVectors:
|
||||||
|
# var a = fromHex(item[0])
|
||||||
|
# var enc = Base58.encode(a)
|
||||||
|
# var dec = Base58.decode(item[1])
|
||||||
|
# check:
|
||||||
|
# enc == item[1]
|
||||||
|
# dec == a
|
||||||
|
# test "Buffer Overrun test":
|
||||||
|
# var encres = ""
|
||||||
|
# var encsize = 0
|
||||||
|
# var decres: seq[byte] = @[]
|
||||||
|
# var decsize = 0
|
||||||
|
# check:
|
||||||
|
# Base58.encode([0'u8], encres, encsize) == Base58Status.Overrun
|
||||||
|
# encsize == 1
|
||||||
|
# Base58.decode("1", decres, decsize) == Base58Status.Overrun
|
||||||
|
# decsize == 5
|
||||||
|
# test "Incorrect test":
|
||||||
|
# var decres = newSeq[byte](10)
|
||||||
|
# var decsize = 0
|
||||||
|
# check:
|
||||||
|
# Base58.decode("l", decres, decsize) == Base58Status.Incorrect
|
||||||
|
# decsize == 0
|
||||||
|
# Base58.decode("2l", decres, decsize) == Base58Status.Incorrect
|
||||||
|
# decsize == 0
|
||||||
|
# Base58.decode("O", decres, decsize) == Base58Status.Incorrect
|
||||||
|
# decsize == 0
|
||||||
|
# Base58.decode("2O", decres, decsize) == Base58Status.Incorrect
|
||||||
|
# decsize == 0
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import ../libp2p/varint
|
import ../libp2p/[varint, errors]
|
||||||
|
|
||||||
const PBedgeValues = [
|
const PBedgeValues = [
|
||||||
0'u64, (1'u64 shl 7) - 1'u64,
|
0'u64, (1'u64 shl 7) - 1'u64,
|
||||||
@ -92,34 +92,71 @@ suite "Variable integer test suite":
|
|||||||
var value = 0'u64
|
var value = 0'u64
|
||||||
for i in 0..<len(PBedgeValues):
|
for i in 0..<len(PBedgeValues):
|
||||||
buffer.setLen(PBedgeSizes[i])
|
buffer.setLen(PBedgeSizes[i])
|
||||||
|
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
value = 0'u64
|
||||||
|
|
||||||
check:
|
check:
|
||||||
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
||||||
PB.getUVarint(buffer, length, value) == VarintStatus.Success
|
PB.getUVarint(buffer, length, value) == VarintStatus.Success
|
||||||
value == PBedgeValues[i]
|
value == PBedgeValues[i]
|
||||||
toHex(buffer) == PBedgeExpects[i]
|
toHex(buffer) == PBedgeExpects[i]
|
||||||
|
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
value = 0'u64
|
||||||
|
|
||||||
|
check PB.putUVarint(buffer, PBedgeValues[i]).isOk == true
|
||||||
|
let res = PB.getUVarint(buffer)
|
||||||
|
check:
|
||||||
|
res.isOk == true
|
||||||
|
res.value.value == PBedgeValues[i]
|
||||||
|
toHex(buffer) == PBedgeExpects[i]
|
||||||
|
|
||||||
test "[ProtoBuf] Buffer Overrun edge cases test":
|
test "[ProtoBuf] Buffer Overrun edge cases test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
var length = 0
|
var length = 0
|
||||||
for i in 0..<len(PBedgeValues):
|
for i in 0..<len(PBedgeValues):
|
||||||
buffer.setLen(PBedgeSizes[i] - 1)
|
buffer.setLen(PBedgeSizes[i] - 1)
|
||||||
let res = PB.putUVarint(buffer, length, PBedgeValues[i])
|
|
||||||
|
if len(buffer) > 0:
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
let res1 = PB.putUVarint(buffer, length, PBedgeValues[i])
|
||||||
check:
|
check:
|
||||||
res == VarintStatus.Overrun
|
res1 == VarintStatus.Overrun
|
||||||
length == PBedgeSizes[i]
|
length == PBedgeSizes[i]
|
||||||
|
|
||||||
|
if len(buffer) > 0:
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
let res2 = PB.putUVarint(buffer, PBedgeValues[i])
|
||||||
|
check:
|
||||||
|
res2.isErr == true
|
||||||
|
res2.error == errors.OverrunError
|
||||||
|
|
||||||
test "[ProtoBuf] Buffer Incomplete edge cases test":
|
test "[ProtoBuf] Buffer Incomplete edge cases test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
var length = 0
|
var length = 0
|
||||||
var value = 0'u64
|
var value = 0'u64
|
||||||
for i in 0..<len(PBedgeValues):
|
for i in 0..<len(PBedgeValues):
|
||||||
buffer.setLen(PBedgeSizes[i])
|
buffer.setLen(PBedgeSizes[i])
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
|
||||||
check:
|
check:
|
||||||
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
||||||
buffer.setLen(len(buffer) - 1)
|
buffer.setLen(len(buffer) - 1)
|
||||||
check:
|
check:
|
||||||
PB.getUVarint(buffer, length, value) == VarintStatus.Incomplete
|
PB.getUVarint(buffer, length, value) == VarintStatus.Incomplete
|
||||||
|
|
||||||
|
buffer.setLen(PBedgeSizes[i])
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
|
||||||
|
check:
|
||||||
|
PB.putUVarint(buffer, PBedgeValues[i]).isOk == true
|
||||||
|
buffer.setLen(len(buffer) - 1)
|
||||||
|
let res = PB.getUVarint(buffer)
|
||||||
|
check:
|
||||||
|
res.isErr == true
|
||||||
|
res.error == errors.IncompleteError
|
||||||
|
|
||||||
test "[ProtoBuf] Integer Overflow 32bit test":
|
test "[ProtoBuf] Integer Overflow 32bit test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
var length = 0
|
var length = 0
|
||||||
@ -138,6 +175,7 @@ suite "Variable integer test suite":
|
|||||||
if PBedgeSizes[i] > 9:
|
if PBedgeSizes[i] > 9:
|
||||||
var value = 0'u64
|
var value = 0'u64
|
||||||
buffer.setLen(PBedgeSizes[i] + 1)
|
buffer.setLen(PBedgeSizes[i] + 1)
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
check:
|
check:
|
||||||
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
PB.putUVarint(buffer, length, PBedgeValues[i]) == VarintStatus.Success
|
||||||
buffer[9] = buffer[9] or 0x80'u8
|
buffer[9] = buffer[9] or 0x80'u8
|
||||||
@ -145,28 +183,63 @@ suite "Variable integer test suite":
|
|||||||
check:
|
check:
|
||||||
PB.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
PB.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
||||||
|
|
||||||
|
buffer.setLen(PBedgeSizes[i] + 1)
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
check:
|
||||||
|
PB.putUVarint(buffer, PBedgeValues[i]).isOk == true
|
||||||
|
buffer[9] = buffer[9] or 0x80'u8
|
||||||
|
buffer[10] = 0x01'u8
|
||||||
|
let res = PB.getUVarint(buffer)
|
||||||
|
check:
|
||||||
|
res.isErr == true
|
||||||
|
res.error == errors.OverflowError
|
||||||
|
|
||||||
test "[LibP2P] Success edge cases test":
|
test "[LibP2P] Success edge cases test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
var length = 0
|
var length = 0
|
||||||
var value = 0'u64
|
var value = 0'u64
|
||||||
for i in 0..<len(LPedgeValues):
|
for i in 0..<len(LPedgeValues):
|
||||||
buffer.setLen(LPedgeSizes[i])
|
buffer.setLen(LPedgeSizes[i])
|
||||||
|
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
value = 0'u64
|
||||||
|
|
||||||
check:
|
check:
|
||||||
LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success
|
LP.putUVarint(buffer, length, LPedgeValues[i]) == VarintStatus.Success
|
||||||
LP.getUVarint(buffer, length, value) == VarintStatus.Success
|
LP.getUVarint(buffer, length, value) == VarintStatus.Success
|
||||||
value == LPedgeValues[i]
|
value == LPedgeValues[i]
|
||||||
toHex(buffer) == LPedgeExpects[i]
|
toHex(buffer) == LPedgeExpects[i]
|
||||||
|
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
value = 0'u64
|
||||||
|
|
||||||
|
check LP.putUVarint(buffer, LPedgeValues[i]).isOk == true
|
||||||
|
let res = LP.getUVarint(buffer)
|
||||||
|
check:
|
||||||
|
res.isOk == true
|
||||||
|
res.value.value == LPedgeValues[i]
|
||||||
|
toHex(buffer) == LPedgeExpects[i]
|
||||||
|
|
||||||
test "[LibP2P] Buffer Overrun edge cases test":
|
test "[LibP2P] Buffer Overrun edge cases test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
var length = 0
|
var length = 0
|
||||||
for i in 0..<len(LPedgeValues):
|
for i in 0..<len(LPedgeValues):
|
||||||
buffer.setLen(PBedgeSizes[i] - 1)
|
buffer.setLen(PBedgeSizes[i] - 1)
|
||||||
let res = LP.putUVarint(buffer, length, LPedgeValues[i])
|
|
||||||
|
if len(buffer) > 0:
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
let res1 = LP.putUVarint(buffer, length, LPedgeValues[i])
|
||||||
check:
|
check:
|
||||||
res == VarintStatus.Overrun
|
res1 == VarintStatus.Overrun
|
||||||
length == LPedgeSizes[i]
|
length == LPedgeSizes[i]
|
||||||
|
|
||||||
|
if len(buffer) > 0:
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
let res2 = LP.putUVarint(buffer, PBedgeValues[i])
|
||||||
|
check:
|
||||||
|
res2.isErr == true
|
||||||
|
res2.error == errors.OverrunError
|
||||||
|
|
||||||
test "[LibP2P] Buffer Incomplete edge cases test":
|
test "[LibP2P] Buffer Incomplete edge cases test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
var length = 0
|
var length = 0
|
||||||
@ -179,6 +252,17 @@ suite "Variable integer test suite":
|
|||||||
check:
|
check:
|
||||||
LP.getUVarint(buffer, length, value) == VarintStatus.Incomplete
|
LP.getUVarint(buffer, length, value) == VarintStatus.Incomplete
|
||||||
|
|
||||||
|
buffer.setLen(LPedgeSizes[i])
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
|
||||||
|
check:
|
||||||
|
LP.putUVarint(buffer, LPedgeValues[i]).isOk == true
|
||||||
|
buffer.setLen(len(buffer) - 1)
|
||||||
|
let res = LP.getUVarint(buffer)
|
||||||
|
check:
|
||||||
|
res.isErr == true
|
||||||
|
res.error == errors.IncompleteError
|
||||||
|
|
||||||
test "[LibP2P] Integer Overflow 32bit test":
|
test "[LibP2P] Integer Overflow 32bit test":
|
||||||
var buffer = newSeq[byte]()
|
var buffer = newSeq[byte]()
|
||||||
var length = 0
|
var length = 0
|
||||||
@ -204,6 +288,17 @@ suite "Variable integer test suite":
|
|||||||
check:
|
check:
|
||||||
LP.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
LP.getUVarint(buffer, length, value) == VarintStatus.Overflow
|
||||||
|
|
||||||
|
buffer.setLen(LPedgeSizes[i] + 1)
|
||||||
|
zeroMem(addr buffer[0], len(buffer))
|
||||||
|
check:
|
||||||
|
LP.putUVarint(buffer, LPedgeValues[i]).isOk == true
|
||||||
|
buffer[8] = buffer[9] or 0x80'u8
|
||||||
|
buffer[9] = 0x01'u8
|
||||||
|
let res = LP.getUVarint(buffer)
|
||||||
|
check:
|
||||||
|
res.isErr == true
|
||||||
|
res.error == errors.OverflowError
|
||||||
|
|
||||||
test "[LibP2P] Over 63bit test":
|
test "[LibP2P] Over 63bit test":
|
||||||
var buffer = newSeq[byte](10)
|
var buffer = newSeq[byte](10)
|
||||||
var length = 0
|
var length = 0
|
||||||
@ -214,3 +309,12 @@ suite "Variable integer test suite":
|
|||||||
0x8000_0000_0000_0000'u64) == VarintStatus.Overflow
|
0x8000_0000_0000_0000'u64) == VarintStatus.Overflow
|
||||||
LP.putUVarint(buffer, length,
|
LP.putUVarint(buffer, length,
|
||||||
0xFFFF_FFFF_FFFF_FFFF'u64) == VarintStatus.Overflow
|
0xFFFF_FFFF_FFFF_FFFF'u64) == VarintStatus.Overflow
|
||||||
|
let r1 = LP.putUVarint(buffer, 0x7FFF_FFFF_FFFF_FFFF'u64)
|
||||||
|
let r2 = LP.putUVarint(buffer, 0x8000_0000_0000_0000'u64)
|
||||||
|
let r3 = LP.putUVarint(buffer, 0xFFFF_FFFF_FFFF_FFFF'u64)
|
||||||
|
check:
|
||||||
|
r1.isOk == true
|
||||||
|
r2.isErr == true
|
||||||
|
r3.isErr == true
|
||||||
|
r2.error == errors.OverflowError
|
||||||
|
r3.error == errors.OverflowError
|
||||||
|
Loading…
x
Reference in New Issue
Block a user