More complete DynamicBytes implementation
This commit is contained in:
parent
9a0f1425c1
commit
74ae794993
|
@ -37,7 +37,7 @@ proc fromJson*[N](n: JsonNode, argName: string, result: var FixedBytes[N]) {.inl
|
||||||
# expects base 16 string, starting with "0x"
|
# expects base 16 string, starting with "0x"
|
||||||
bytesFromJson(n, argName, array[N, byte](result))
|
bytesFromJson(n, argName, array[N, byte](result))
|
||||||
|
|
||||||
proc fromJson*[N](n: JsonNode, argName: string, result: var DynamicBytes[N]) {.inline.} =
|
proc fromJson*(n: JsonNode, argName: string, result: var DynamicBytes) {.inline.} =
|
||||||
n.kind.expect(JString, argName)
|
n.kind.expect(JString, argName)
|
||||||
result = fromHex(type result, n.getStr())
|
result = fromHex(type result, n.getStr())
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ proc `%`*(v: Quantity): JsonNode =
|
||||||
proc `%`*[N](v: FixedBytes[N]): JsonNode =
|
proc `%`*[N](v: FixedBytes[N]): JsonNode =
|
||||||
result = %("0x" & array[N, byte](v).toHex)
|
result = %("0x" & array[N, byte](v).toHex)
|
||||||
|
|
||||||
proc `%`*[N](v: DynamicBytes[N]): JsonNode =
|
proc `%`*(v: DynamicBytes): JsonNode =
|
||||||
result = %("0x" & toHex(v))
|
result = %("0x" & toHex(v))
|
||||||
|
|
||||||
proc `%`*(v: Address): JsonNode =
|
proc `%`*(v: Address): JsonNode =
|
||||||
|
@ -75,7 +75,7 @@ proc writeHexValue(w: JsonWriter, v: openarray[byte]) =
|
||||||
w.stream.writeHex v
|
w.stream.writeHex v
|
||||||
w.stream.write "\""
|
w.stream.write "\""
|
||||||
|
|
||||||
proc writeValue*[N](w: var JsonWriter, v: DynamicBytes[N]) =
|
proc writeValue*(w: var JsonWriter, v: DynamicBytes) =
|
||||||
writeHexValue w, distinctBase(v)
|
writeHexValue w, distinctBase(v)
|
||||||
|
|
||||||
proc writeValue*[N](w: var JsonWriter, v: FixedBytes[N]) =
|
proc writeValue*[N](w: var JsonWriter, v: FixedBytes[N]) =
|
||||||
|
@ -87,7 +87,7 @@ proc writeValue*(w: var JsonWriter, v: Address) =
|
||||||
proc writeValue*(w: var JsonWriter, v: TypedTransaction) =
|
proc writeValue*(w: var JsonWriter, v: TypedTransaction) =
|
||||||
writeHexValue w, distinctBase(v)
|
writeHexValue w, distinctBase(v)
|
||||||
|
|
||||||
proc readValue*[N](r: var JsonReader, T: type DynamicBytes[N]): T =
|
proc readValue*(r: var JsonReader, T: type DynamicBytes): T =
|
||||||
fromHex(T, r.readValue(string))
|
fromHex(T, r.readValue(string))
|
||||||
|
|
||||||
proc readValue*[N](r: var JsonReader, T: type FixedBytes[N]): T =
|
proc readValue*[N](r: var JsonReader, T: type FixedBytes[N]): T =
|
||||||
|
@ -108,7 +108,7 @@ proc `$`*(v: Address): string {.inline.} =
|
||||||
proc `$`*(v: TypedTransaction): string {.inline.} =
|
proc `$`*(v: TypedTransaction): string {.inline.} =
|
||||||
"0x" & distinctBase(v).toHex
|
"0x" & distinctBase(v).toHex
|
||||||
|
|
||||||
proc `$`*[N](v: DynamicBytes[N]): string {.inline.} =
|
proc `$`*(v: DynamicBytes): string {.inline.} =
|
||||||
"0x" & toHex(v)
|
"0x" & toHex(v)
|
||||||
|
|
||||||
proc `%`*(x: EthSend): JsonNode =
|
proc `%`*(x: EthSend): JsonNode =
|
||||||
|
|
|
@ -62,10 +62,13 @@ func encodeDynamic(v: openarray[byte]): EncodeResult =
|
||||||
result.data &= y.toHex.toLower
|
result.data &= y.toHex.toLower
|
||||||
result.data &= "00".repeat(v.len mod 32)
|
result.data &= "00".repeat(v.len mod 32)
|
||||||
|
|
||||||
func encode*[N](x: DynamicBytes[N]): EncodeResult {.inline.} =
|
func encode*(x: DynamicBytes): EncodeResult {.inline.} =
|
||||||
encodeDynamic(distinctBase(x))
|
encodeDynamic(distinctBase x)
|
||||||
|
|
||||||
func decodeDynamic(input: string, offset: int, to: var openarray[byte]): int =
|
func decodeDynamic(input: string,
|
||||||
|
offset: int,
|
||||||
|
minLen, maxLen: int,
|
||||||
|
to: var openarray[byte]): int =
|
||||||
var dataOffset, dataLen: UInt256
|
var dataOffset, dataLen: UInt256
|
||||||
result = decode(input, offset, dataOffset)
|
result = decode(input, offset, dataOffset)
|
||||||
discard decode(input, dataOffset.truncate(int) * 2, dataLen)
|
discard decode(input, dataOffset.truncate(int) * 2, dataLen)
|
||||||
|
@ -74,9 +77,8 @@ func decodeDynamic(input: string, offset: int, to: var openarray[byte]): int =
|
||||||
let actualDataOffset = (dataOffset.truncate(int) + 32) * 2
|
let actualDataOffset = (dataOffset.truncate(int) + 32) * 2
|
||||||
hexToByteArray(input[actualDataOffset .. actualDataOffset + meaningfulLen - 1], to)
|
hexToByteArray(input[actualDataOffset .. actualDataOffset + meaningfulLen - 1], to)
|
||||||
|
|
||||||
func decode*[N](input: string, offset: int, to: var DynamicBytes[N]): int {.inline.} =
|
func decode*(input: string, offset: int, to: var DynamicBytes): int {.inline.} =
|
||||||
{.fatal: "decodeDynamic is not implemented properly".}
|
decodeDynamic(input, offset, to.minLen, to.maxLen, distinctBase(to))
|
||||||
decodeDynamic(input, offset, distinctBase(to))
|
|
||||||
|
|
||||||
macro makeTypeEnum(): untyped =
|
macro makeTypeEnum(): untyped =
|
||||||
## This macro creates all the various types of Solidity contracts and maps
|
## This macro creates all the various types of Solidity contracts and maps
|
||||||
|
|
|
@ -9,7 +9,9 @@ type
|
||||||
highestBlock*: int
|
highestBlock*: int
|
||||||
|
|
||||||
FixedBytes*[N: static[int]] = distinct array[N, byte]
|
FixedBytes*[N: static[int]] = distinct array[N, byte]
|
||||||
DynamicBytes*[MaxLen: static[int]] = distinct seq[byte]
|
DynamicBytes*[
|
||||||
|
minLen: static[int] = 0,
|
||||||
|
maxLen: static[int] = high(int)] = distinct seq[byte]
|
||||||
|
|
||||||
Address* = distinct array[20, byte]
|
Address* = distinct array[20, byte]
|
||||||
TxHash* = FixedBytes[32]
|
TxHash* = FixedBytes[32]
|
||||||
|
@ -210,7 +212,7 @@ type
|
||||||
gasLimit*: Quantity
|
gasLimit*: Quantity
|
||||||
gasUsed*: Quantity
|
gasUsed*: Quantity
|
||||||
timestamp*: Quantity
|
timestamp*: Quantity
|
||||||
extraData*: DynamicBytes[32]
|
extraData*: DynamicBytes[32, 32]
|
||||||
baseFeePerGas*: UInt256
|
baseFeePerGas*: UInt256
|
||||||
blockHash*: BlockHash
|
blockHash*: BlockHash
|
||||||
transactions*: seq[TypedTransaction]
|
transactions*: seq[TypedTransaction]
|
||||||
|
@ -218,7 +220,7 @@ type
|
||||||
template `==`*[N](a, b: FixedBytes[N]): bool =
|
template `==`*[N](a, b: FixedBytes[N]): bool =
|
||||||
distinctBase(a) == distinctBase(b)
|
distinctBase(a) == distinctBase(b)
|
||||||
|
|
||||||
template `==`*[N](a, b: DynamicBytes[N]): bool =
|
template `==`*[minLen, maxLen](a, b: DynamicBytes[minLen, maxLen]): bool =
|
||||||
distinctBase(a) == distinctBase(b)
|
distinctBase(a) == distinctBase(b)
|
||||||
|
|
||||||
proc `==`*(a, b: Address): bool {.inline.} =
|
proc `==`*(a, b: Address): bool {.inline.} =
|
||||||
|
@ -239,7 +241,7 @@ func hash*[N](bytes: FixedBytes[N]): Hash =
|
||||||
template toHex*[N](x: FixedBytes[N]): string =
|
template toHex*[N](x: FixedBytes[N]): string =
|
||||||
toHex(distinctBase x)
|
toHex(distinctBase x)
|
||||||
|
|
||||||
template toHex*[N](x: DynamicBytes[N]): string =
|
template toHex*[minLen, maxLen](x: DynamicBytes[minLen, maxLen]): string =
|
||||||
toHex(distinctBase x)
|
toHex(distinctBase x)
|
||||||
|
|
||||||
template toHex*(x: Address): string =
|
template toHex*(x: Address): string =
|
||||||
|
@ -248,14 +250,6 @@ template toHex*(x: Address): string =
|
||||||
template fromHex*(T: type Address, hexStr: string): T =
|
template fromHex*(T: type Address, hexStr: string): T =
|
||||||
T fromHex(distinctBase(T), hexStr)
|
T fromHex(distinctBase(T), hexStr)
|
||||||
|
|
||||||
func fromHex*[N](T: type DynamicBytes[N], hexStr: string): T =
|
|
||||||
if hexStr.len > N * 2:
|
|
||||||
raise newException(ValueError, "hex input too large")
|
|
||||||
T hexToSeqByte(hexStr)
|
|
||||||
|
|
||||||
template fromHex*[N](T: type FixedBytes[N], hexStr: string): T =
|
|
||||||
T fromHex(distinctBase(T), hexStr)
|
|
||||||
|
|
||||||
template skip0xPrefix(hexStr: string): int =
|
template skip0xPrefix(hexStr: string): int =
|
||||||
## Returns the index of the first meaningful char in `hexStr` by skipping
|
## Returns the index of the first meaningful char in `hexStr` by skipping
|
||||||
## "0x" prefix
|
## "0x" prefix
|
||||||
|
@ -269,3 +263,24 @@ proc strip0xPrefix*(s: string): string =
|
||||||
else:
|
else:
|
||||||
s
|
s
|
||||||
|
|
||||||
|
func fromHex*[minLen](T: type DynamicBytes[minLen, maxLen], hexStr: string): T =
|
||||||
|
let prefixLen = skip0xPrefix(hexStr)
|
||||||
|
let hexDataLen = hexStr.len - prefixLen
|
||||||
|
|
||||||
|
if hexDataLen < minLen * 2:
|
||||||
|
raise newException(ValueError, "hex input too small")
|
||||||
|
|
||||||
|
if hexDataLen > maxLen * 2:
|
||||||
|
raise newException(ValueError, "hex input too large")
|
||||||
|
|
||||||
|
T hexToSeqByte(hexStr)
|
||||||
|
|
||||||
|
template fromHex*[N](T: type FixedBytes[N], hexStr: string): T =
|
||||||
|
T fromHex(distinctBase(T), hexStr)
|
||||||
|
|
||||||
|
proc toArray*[N](data: DynamicBytes[N, N]): array[N, byte] =
|
||||||
|
copyMem(addr result[0], unsafeAddr distinctBase(data)[0], N)
|
||||||
|
|
||||||
|
template bytes*(data: DynamicBytes): seq[byte] =
|
||||||
|
distinctBase data
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue