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.
This commit is contained in:
Zahary Karadjov 2018-06-27 02:40:49 +03:00
parent 9959863512
commit d75b09795b
2 changed files with 36 additions and 12 deletions

12
rlp.nim
View File

@ -96,9 +96,13 @@ proc lengthBytesCount(self: Rlp): int =
return int(marker - LEN_PREFIXED_LIST_MARKER) return int(marker - LEN_PREFIXED_LIST_MARKER)
return 0 return 0
proc isSingleByte(self: Rlp): bool = proc isSingleByte*(self: Rlp): bool =
hasData() and bytes[position] < BLOB_START_MARKER hasData() and bytes[position] < BLOB_START_MARKER
proc getByteValue*(self: Rlp): byte =
assert self.isSingleByte()
return bytes[position]
proc payloadOffset(self: Rlp): int = proc payloadOffset(self: Rlp): int =
if isSingleByte(): 0 else: 1 + lengthBytesCount() 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) template maxBytes*(o: typedesc[Ordinal | uint64 | uint]): int = sizeof(o)
proc toInt*(self: Rlp, IntType: typedesc): IntType = 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 # XXX: self insertions are not working in generic procs
# https://github.com/nim-lang/Nim/issues/5053 # 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") raise newException(RlpTypeMismatch, "The RLP contains a larger than expected Int value")
for i in payloadStart ..< (payloadStart + payloadSize): 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 = proc toString*(self: Rlp): string =
if not isBlob(): if not isBlob():

View File

@ -13,17 +13,23 @@ type
PrematureFinalizationError* = object of Exception 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 * y is T
x - y is T x - y is T
x div y is T x div y is T
x mod 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 const
wrapObjectsInList* = true wrapObjectsInList* = true
@ -35,14 +41,16 @@ proc bytesNeeded(num: Integer): int =
inc result inc result
n = n shr 8 n = n shr 8
proc writeBigEndian(outStream: var Bytes, number: int, proc writeBigEndian(outStream: var Bytes, number: Integer,
lastByteIdx: int, numberOfBytes: int) = lastByteIdx: int, numberOfBytes: int) =
mixin `and`, `shr`
var n = number var n = number
for i in countdown(lastByteIdx, lastByteIdx - int(numberOfBytes) + 1): for i in countdown(lastByteIdx, lastByteIdx - int(numberOfBytes) + 1):
outStream[i] = byte(n and 0xff) outStream[i] = byte(n and 0xff)
n = n shr 8 n = n shr 8
proc writeBigEndian(outStream: var Bytes, number: int, proc writeBigEndian(outStream: var Bytes, number: Integer,
numberOfBytes: int) {.inline.} = numberOfBytes: int) {.inline.} =
outStream.setLen(outStream.len + numberOfBytes) outStream.setLen(outStream.len + numberOfBytes)
outStream.writeBigEndian(number, outStream.len - 1, numberOfBytes) outStream.writeBigEndian(number, outStream.len - 1, numberOfBytes)
@ -161,7 +169,9 @@ proc appendBytesRange(self; data: BytesRange) =
proc appendImpl(self; data: MemRange) = proc appendImpl(self; data: MemRange) =
appendBlob(self, data, BLOB_START_MARKER) 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) type IntType = type(i)
if i == IntType(0): if i == IntType(0):
@ -171,10 +181,13 @@ proc appendImpl(self; i: Integer) =
else: else:
let bytesNeeded = i.bytesNeeded let bytesNeeded = i.bytesNeeded
self.output.writeCount(bytesNeeded, BLOB_START_MARKER) self.output.writeCount(bytesNeeded, BLOB_START_MARKER)
self.output.writeBigEndian(i.int, bytesNeeded) self.output.writeBigEndian(i, bytesNeeded)
self.maybeClosePendingLists() self.maybeClosePendingLists()
template appendImpl(self; i: Integer) =
appendInt(self, i)
template appendImpl(self; e: enum) = template appendImpl(self; e: enum) =
appendImpl(self, int(e)) appendImpl(self, int(e))
@ -235,6 +248,11 @@ proc encode*[T](v: T): BytesRange =
writer.append(v) writer.append(v)
return writer.finish return writer.finish
proc encodeInt*(i: Integer): BytesRange =
var writer = initRlpWriter()
writer.appendInt(i)
return writer.finish
macro encodeList*(args: varargs[untyped]): BytesRange = macro encodeList*(args: varargs[untyped]): BytesRange =
var var
listLen = args.len listLen = args.len