## Nim-LibP2P ## Copyright (c) 2020 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 chronos, chronicles import ringbuffer, stream, utils, ../varint, ../vbuffer const DefaultBuffSize* = 1 shl 20 SafeVarintSize* = sizeof(uint) type InvalidVarintException* = object of CatchableError InvalidVarintSizeException* = object of CatchableError LenPrefixed* = ref object readBuff: RingBuffer[byte] buff: seq[byte] pos, size: int mode: Mode Mode {.pure.} = enum Decoding, Reading proc newInvalidVarintException*(): ref InvalidVarintException = newException(InvalidVarintException, "Unable to parse varint") proc newInvalidVarintSizeException*(): ref InvalidVarintSizeException = newException(InvalidVarintSizeException, "Wrong varint size") proc init*(lp: type[LenPrefixed], maxSize: int = DefaultBuffSize): lp = LenPrefixed(readBuff: RingBuffer[byte].init(maxSize), buff: newSeq[byte](maxSize), # TODO: don't allocate all - grow dinamicaly mode: Mode.Decoding, pos: 0, size: 0) proc decodeLen(lp: LenPrefixed): int = var size: uint length: int res: VarintStatus for i in 0..SafeVarintSize: lp.buff[i] = lp.readBuff.read(1)[0] res = LP.getUVarint(lp.buff.toOpenArray(0, i), length, size) if res == VarintStatus.Success: break if length > SafeVarintSize: raise newInvalidVarintSizeException() if size.int <= 0: raise newInvalidVarintSizeException() return size.int proc read(lp: LenPrefixed, chunk: Future[seq[byte]]): Future[seq[byte]] {.async, gcsafe.} = try: lp.readBuff.append((await chunk)) while lp.readBuff.len > 0: case lp.mode: of Mode.Decoding: lp.size = lp.decodeLen() lp.mode = Mode.Reading else: var last = lp.pos + lp.size - 1 if last <= 0: last = 1 var read = lp.readBuff.read(lp.buff.toOpenArray(lp.pos, last)) lp.size -= read lp.pos += read if lp.size == 0: lp.mode = Mode.Decoding result = lp.buff[0..