From b5fe8dc46e569e7673458281e7e11694d6a41376 Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Sat, 26 Mar 2022 13:50:35 -0600 Subject: [PATCH] make Leo a case object --- leopard/leopard.nim | 182 +++++++++++++++++++++++++++----------------- 1 file changed, 111 insertions(+), 71 deletions(-) diff --git a/leopard/leopard.nim b/leopard/leopard.nim index 760bc7e..bf98044 100644 --- a/leopard/leopard.nim +++ b/leopard/leopard.nim @@ -24,28 +24,40 @@ const BuffMultiples* = 64 type - LeoBufferPtr = ptr UncheckedArray[byte] - Leo = object of RootObj + LeoBufferPtr* = ptr UncheckedArray[byte] + + LeoCoderKind* {.pure.} = enum + Encoder, + Decoder + + Leo* = object of RootObj bufSize*: int # size of the buffer in multiples of 64 buffers*: int # total number of data buffers (K) parity*: int # total number of parity buffers (M) dataBufferPtr: seq[LeoBufferPtr] # buffer where data is copied before encoding - parityWorkCount: int # number of parity work buffers - parityBufferPtr: seq[LeoBufferPtr] # buffer where parity is copied before encoding - - LeoEncoder* = object of Leo - LeoDecoder* = object of Leo - decodeWorkCount: int # number of decoding work buffers - decodeBufferPtr: seq[LeoBufferPtr] # work buffer used for decoding + workBufferCount: int # number of parity work buffers + workBufferPtr: seq[LeoBufferPtr] # buffer where parity is copied before encoding + case kind: LeoCoderKind + of LeoCoderKind.Decoder: + decodeBufferCount: int # number of decoding work buffers + decodeBufferPtr: seq[LeoBufferPtr] # work buffer used for decoding + of LeoCoderKind.Encoder: + discard proc encode*( - self: var LeoEncoder, + self: var Leo, data, parity: var openArray[seq[byte]]): Result[void, cstring] = + ## Encode a list of buffers in `data` into a number of `bufSize` sized + ## `parity` buffers + ## + ## `data` - list of original data `buffers` of size `bufSize` + ## `parity` - list of parity `buffers` of size `bufSize` + ## # zero encode work buffer to avoid corrupting with previous run - for i in 0.. 0: - parityPtr[i] = self.parityBufferPtr[i] - copyMem(self.parityBufferPtr[i], addr parity[i][0], self.bufSize) + parityPtr[i] = self.workBufferPtr[i] + copyMem(self.workBufferPtr[i], addr parity[i][0], self.bufSize) else: parityPtr[i] = nil @@ -109,9 +130,9 @@ proc decode*( self.bufSize.cuint, self.buffers.cuint, self.parity.cuint, - self.decodeWorkCount.cuint, + self.decodeBufferCount.cuint, cast[ptr pointer](addr dataPtr[0]), - cast[ptr pointer](addr self.parityBufferPtr[0]), + cast[ptr pointer](addr self.workBufferPtr[0]), cast[ptr pointer](addr self.decodeBufferPtr[0])) if ord(res) != ord(LeopardSuccess): @@ -124,14 +145,35 @@ proc decode*( ok() -proc free*(self: var Leo) = discard -# for i in 0.. 0: + for i, p in self.workBufferPtr: + p.leoFree() + self.workBufferPtr[i] = nil -# for i in 0.. 0: + for i, p in self.dataBufferPtr: + p.leoFree() + self.dataBufferPtr[i] = nil + + self.dataBufferPtr.setLen(0) + + if self.kind == LeoCoderKind.Decoder: + if self.decodeBufferPtr.len > 0: + for i, p in self.decodeBufferPtr: + p.leoFree() + self.decodeBufferPtr[i] = nil + self.decodeBufferPtr.setLen(0) + +# TODO: The destructor doesn't behave as +# I'd expect it, it's called many more times +# than it should. This is however, most +# likely my misinterpretation of how it should +# work. +# proc `=destroy`*(self: var Leo) = +# self.free() proc setup*(self: var Leo, bufSize, buffers, parity: int): Result[void, cstring] = if bufSize mod BuffMultiples != 0: @@ -149,50 +191,48 @@ proc setup*(self: var Leo, bufSize, buffers, parity: int): Result[void, cstring] return ok() -proc init*(T: type LeoEncoder, bufSize, buffers, parity: int): Result[T, cstring] = +proc init*(T: type Leo, bufSize, buffers, parity: int, kind: LeoCoderKind): Result[T, cstring] = + if bufSize mod BuffMultiples != 0: + return err("bufSize should be multiples of 64 bytes!") + + once: + # First, attempt to init the library, + # this happens only once for all threads and + # should be safe as internal tables are only read, + # never written. However instantiation should be + # synchronized, since two instances can attempt to + # concurrently instantiate the library twice, and + # might end up with two distinct versions - not a big + # deal but will defeat the purpose of this `once` block + if (let res = leoinit(); res.ord != LeopardSuccess.ord): + return err(leoResultString(res.LeopardResult)) + var - self = LeoEncoder() + self = Leo( + kind: kind, + bufSize: bufSize, + buffers: buffers, + parity: parity) - ? Leo(self).setup(bufSize, buffers, parity) - - self.parityWorkCount = leoEncodeWorkCount( + self.workBufferCount = leoEncodeWorkCount( buffers.cuint, parity.cuint).int # initialize encode work buffers - for _ in 0..