Dmitriy Ryajov 41cd86df5b
High level wrapper (#3)
* initial implementation and tests

* [wip] refactor checking of RS code validity

* [wip] point GHA badge link to main branch instead of initial_impl

* [wip] delete leftover echo at bottom of test_leopard.nim

* [wip] add basic usage info to README

* [wip] more basic info added to README re: requirements, installation, usage

* [wip] add config.nims with --tlsEmulation:off to check if it helps with perf on Windows

* [wip] use `object` instead of `object of CatchableError` for LeopardError

workaround for edge case encountered in context of nimbus-build-system project

* [wip] clarify wording in README re: stability

* [wip] can use `object of CatchableError` for LeopardError with workaround

* Initial implementation

* make Leo a case object

* initial test

* cleanup

* remove echo

* use `func` where possible

* comments, misc

* make construction more convenient

* add more tests

* more tests

* unused warnings

* remove sideeffects pragma

* fix importc pragma on unix

* fix windows build

* fix ci

* better warning

* adding more comprehensive tests

* moar tests

* add TODO for usage

* Update leopard/leopard.nim

Co-authored-by: Michael Bradley <michaelsbradleyjr@gmail.com>

* Update leopard/wrapper.nim

Co-authored-by: Michael Bradley <michaelsbradleyjr@gmail.com>

* add tests to reuse same encoder/decoder

* check that parity and data buffers are < 65536

* test that data+parity isn't > 65536

Co-authored-by: Michael Bradley, Jr <michaelsbradleyjr@gmail.com>
2022-03-28 18:42:45 -06:00

81 lines
2.3 KiB
Nim

## Nim-Leopard
## Copyright (c) 2022 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 pkg/upraises
push: {.upraises: [].}
{.deadCodeElim: on.}
import system/ansi_c
import ./cpuinfo_x86
## inspired by https://github.com/mratsim/weave/blob/master/weave/memory/allocs.nim
let
LeoAlignBytes* = if hasAvx2(): 32'u else: 16'u
when defined(windows):
proc alignedAllocWindows(size, alignment: csize_t): pointer
{.importc: "_aligned_malloc", header: "<malloc.h>".}
# Beware of the arg order!
proc alignedAlloc(alignment, size: csize_t): pointer =
alignedAllocWindows(size, alignment)
proc alignedFree*[T](p: ptr T)
{.importc: "_aligned_free", header: "<malloc.h>".}
elif defined(osx):
proc posix_memalign(mem: var pointer, alignment, size: csize_t)
{.importc, header:"<stdlib.h>".}
proc alignedAlloc(alignment, size: csize_t): pointer {.inline.} =
posix_memalign(result, alignment, size)
proc alignedFree*[T](p: ptr T) {.inline.} =
c_free(p)
elif defined(unix):
proc alignedAlloc(alignment, size: csize_t): pointer
{.importc: "aligned_alloc", header: "<stdlib.h>".}
proc alignedFree*[T](p: ptr T) {.inline.} =
c_free(p)
else:
{.warning: "Falling back to manual pointer alignment, this is highly inefficient!".}
proc alignedAlloc*(size, align: Positive): pointer {.inline.} =
var
data = c_malloc(align + size)
if not isNil(data):
var
doffset = cast[uint](data) mod align
data = data.offset((align + doffset).int)
var
offsetPtr = cast[pointer](cast[uint](data) - 1'u)
moveMem(offsetPtr, addr doffset, sizeof(doffset))
return data
proc freeAligned*[T](p: ptr T, align: Positive) {.inline.} =
var data = p
if not isNil(data):
let offset = cast[uint](data) - 1'u
if offset >= align:
return
data = cast[pointer](cast[uint](data) - (align - offset))
c_free(data)
proc leoAlloc*(size: Positive): pointer {.inline.} =
alignedAlloc(LeoAlignBytes, size.csize_t)
proc leoFree*[T](p: ptr T) =
alignedFree(p)