mirror of
https://github.com/logos-storage/nim-leopard.git
synced 2026-01-02 13:43:08 +00:00
Refactor public API to use `var openArray[seq[byte]]` instead of raw pointers for ORC compatibility. The previous API required callers to extract raw pointers from seqs before calling encode/decode. With refc and shallowCopy, reference counting kept buffers alive. ORC doesn't track raw pointers and can reallocate seq buffers at yield points, leaving pointers dangling. The new openArray API borrows data safely. Also updates CI to Nim 2.2.4 and bumps version to 0.2.0. Part of https://github.com/logos-storage/nim-leopard/issues/24 Signed-off-by: Chrysostomos Nanakos <chris@include.gr>
106 lines
2.4 KiB
Nim
106 lines
2.4 KiB
Nim
import std/random
|
|
|
|
import pkg/results
|
|
import ../leopard
|
|
|
|
proc randomCRCPacket*(data: var openArray[byte]) =
|
|
if data.len < 16:
|
|
data[0] = rand(data.len).byte
|
|
for i in 1..<data.len:
|
|
data[i] = data[0]
|
|
else:
|
|
let
|
|
len: uint32 = data.len.uint32
|
|
|
|
copyMem(addr data[0], unsafeAddr len, sizeof(len))
|
|
var
|
|
crc = data.len.uint32
|
|
|
|
for i in 8..<data.len:
|
|
let v = rand(data.len).byte
|
|
data[i] = v
|
|
crc = (crc shl 3) and (crc shr (32 - 3))
|
|
crc += v
|
|
|
|
copyMem(addr data[4], unsafeAddr crc, sizeof(crc))
|
|
|
|
proc checkCRCPacket*(data: openArray[byte]): bool =
|
|
if data.len < 16:
|
|
for d in data[1 .. data.high]:
|
|
if d != data[0]:
|
|
raise (ref Defect)(msg: "Packet don't match")
|
|
else:
|
|
var
|
|
crc = data.len.uint32
|
|
packCrc: uint32
|
|
packSize: uint32
|
|
|
|
copyMem(addr packSize, unsafeAddr data[0], sizeof(packSize))
|
|
if packSize != data.len.uint:
|
|
raise (ref Defect)(msg: "Packet size don't match!")
|
|
|
|
for i in 4..< data.len:
|
|
let v = data[i]
|
|
crc = (crc shl 3) and (crc shr (32 - 3))
|
|
crc += v
|
|
|
|
copyMem(addr packCrc, unsafeAddr data[4], sizeof(packCrc))
|
|
|
|
if packCrc == crc:
|
|
return true
|
|
|
|
proc dropRandomIdx*(bufs: var openArray[seq[byte]], dropCount: int) =
|
|
var
|
|
count = 0
|
|
dups: seq[int]
|
|
size = bufs.len
|
|
|
|
while count < dropCount:
|
|
let i = rand(0..<size)
|
|
if dups.find(i) == -1:
|
|
dups.add(i)
|
|
bufs[i].setLen(0)
|
|
count.inc
|
|
|
|
proc testPackets*(
|
|
buffers,
|
|
parity,
|
|
bufSize,
|
|
dataLosses: int,
|
|
parityLosses: int,
|
|
encoder: var LeoEncoder,
|
|
decoder: var LeoDecoder): Result[void, cstring] =
|
|
|
|
var
|
|
dataBuf = newSeqOfCap[seq[byte]](buffers)
|
|
parityBuf = newSeqOfCap[seq[byte]](parity)
|
|
recoveredBuf = newSeqOfCap[seq[byte]](buffers)
|
|
|
|
for i in 0..<buffers:
|
|
var dataSeq = newSeq[byte](bufSize)
|
|
|
|
randomCRCPacket(dataSeq)
|
|
dataBuf.add(dataSeq)
|
|
|
|
recoveredBuf.add(newSeq[byte](bufSize))
|
|
|
|
for _ in 0 ..< parity:
|
|
parityBuf.add(newSeq[byte](bufSize))
|
|
|
|
encoder.encode(dataBuf, parityBuf).tryGet()
|
|
|
|
if dataLosses > 0:
|
|
dropRandomIdx(dataBuf, dataLosses)
|
|
|
|
if parityLosses > 0:
|
|
dropRandomIdx(parityBuf, parityLosses)
|
|
|
|
decoder.decode(dataBuf, parityBuf, recoveredBuf).tryGet()
|
|
|
|
for i, d in dataBuf:
|
|
if d.len <= 0:
|
|
if not checkCRCPacket(recoveredBuf[i]):
|
|
return err(("Check failed for packet " & $i).cstring)
|
|
|
|
ok()
|