From d75b09795b81f869b5421abfafc3c0d26379640f Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 27 Jun 2018 02:40:49 +0300 Subject: [PATCH] disable the IntLike concept The Stint types don't conform to it at the moment anyway and this simplifies the error messages in many situations. --- rlp.nim | 12 +++++++++--- rlp/writer.nim | 36 +++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/rlp.nim b/rlp.nim index 603d698..173f35d 100644 --- a/rlp.nim +++ b/rlp.nim @@ -96,9 +96,13 @@ proc lengthBytesCount(self: Rlp): int = return int(marker - LEN_PREFIXED_LIST_MARKER) return 0 -proc isSingleByte(self: Rlp): bool = +proc isSingleByte*(self: Rlp): bool = hasData() and bytes[position] < BLOB_START_MARKER +proc getByteValue*(self: Rlp): byte = + assert self.isSingleByte() + return bytes[position] + proc payloadOffset(self: Rlp): int = if isSingleByte(): 0 else: 1 + lengthBytesCount() @@ -175,7 +179,9 @@ proc isInt*(self: Rlp): bool = template maxBytes*(o: typedesc[Ordinal | uint64 | uint]): int = sizeof(o) proc toInt*(self: Rlp, IntType: typedesc): IntType = - mixin maxBytes + # XXX: work-around a Nim issue with typedesc parameters + type OutputType = IntType + mixin maxBytes, to # XXX: self insertions are not working in generic procs # https://github.com/nim-lang/Nim/issues/5053 @@ -193,7 +199,7 @@ proc toInt*(self: Rlp, IntType: typedesc): IntType = raise newException(RlpTypeMismatch, "The RLP contains a larger than expected Int value") for i in payloadStart ..< (payloadStart + payloadSize): - result = cast[IntType](result shl 8) or cast[IntType](self.bytes[self.position + i]) + result = (result shl 8) or OutputType(self.bytes[self.position + i]) proc toString*(self: Rlp): string = if not isBlob(): diff --git a/rlp/writer.nim b/rlp/writer.nim index 44e6260..a7cd2ed 100644 --- a/rlp/writer.nim +++ b/rlp/writer.nim @@ -13,17 +13,23 @@ type PrematureFinalizationError* = object of Exception - IntLike* = concept x, y, type T + IntLike* = concept x, y + type T = type(x) + + # arithmetic ops x + y is T x * y is T x - y is T x div y is T x mod y is T - x shr y is T - x shl y is T - x and int # for masking - Integer* = SomeInteger or IntLike + # some int compatibility required for big endian encoding: + x shr int is T + x shl int is T + x and 0xff is int + x < 128 is bool + + Integer* = SomeInteger # or IntLike const wrapObjectsInList* = true @@ -35,14 +41,16 @@ proc bytesNeeded(num: Integer): int = inc result n = n shr 8 -proc writeBigEndian(outStream: var Bytes, number: int, +proc writeBigEndian(outStream: var Bytes, number: Integer, lastByteIdx: int, numberOfBytes: int) = + mixin `and`, `shr` + var n = number for i in countdown(lastByteIdx, lastByteIdx - int(numberOfBytes) + 1): outStream[i] = byte(n and 0xff) n = n shr 8 -proc writeBigEndian(outStream: var Bytes, number: int, +proc writeBigEndian(outStream: var Bytes, number: Integer, numberOfBytes: int) {.inline.} = outStream.setLen(outStream.len + numberOfBytes) outStream.writeBigEndian(number, outStream.len - 1, numberOfBytes) @@ -161,7 +169,9 @@ proc appendBytesRange(self; data: BytesRange) = proc appendImpl(self; data: MemRange) = appendBlob(self, data, BLOB_START_MARKER) -proc appendImpl(self; i: Integer) = +proc appendInt(self; i: Integer) = + # this is created as a separate proc as an extra precaution against + # any overloading resolution problems when matching the IntLike concept. type IntType = type(i) if i == IntType(0): @@ -171,10 +181,13 @@ proc appendImpl(self; i: Integer) = else: let bytesNeeded = i.bytesNeeded self.output.writeCount(bytesNeeded, BLOB_START_MARKER) - self.output.writeBigEndian(i.int, bytesNeeded) + self.output.writeBigEndian(i, bytesNeeded) self.maybeClosePendingLists() +template appendImpl(self; i: Integer) = + appendInt(self, i) + template appendImpl(self; e: enum) = appendImpl(self, int(e)) @@ -235,6 +248,11 @@ proc encode*[T](v: T): BytesRange = writer.append(v) return writer.finish +proc encodeInt*(i: Integer): BytesRange = + var writer = initRlpWriter() + writer.appendInt(i) + return writer.finish + macro encodeList*(args: varargs[untyped]): BytesRange = var listLen = args.len