nim-ffi/ffi/cbor_serial.nim
2026-07-15 11:46:05 -03:00

47 lines
1.7 KiB
Nim

## `cbor_serialization` wrapper adapting its exception API to `Result[T, string]` for the FFI layer.
## `.ffi.` payloads (plain `object` and `ref T`) cross as value copies; raw `pointer`/`ptr T` are
## rejected at macro-expansion time (see `rejectRawPtrType`).
import system/ansi_c
import cbor_serialization, cbor_serialization/std/options, results
export cbor_serialization, options, results
const CborNullByte*: byte = 0xf6'u8
## CBOR `null` — wire sentinel for empty OK payloads.
proc cborEncode*[T](x: T): seq[byte] =
return Cbor.encode(x)
proc cborEncodeShared*[T](x: T): tuple[data: ptr UncheckedArray[byte], len: int] =
## Encodes `x` into a caller-owned `c_malloc` buffer (free via `cborFreeShared`).
## Empty payloads return `(nil, 0)` without allocating.
let bytes = Cbor.encode(x)
if bytes.len == 0:
return (nil, 0)
let buf = cast[ptr UncheckedArray[byte]](c_malloc(csize_t(bytes.len)))
copyMem(buf, unsafeAddr bytes[0], bytes.len)
return (buf, bytes.len)
proc cborFreeShared*(data: var ptr UncheckedArray[byte]) =
## Frees a `cborEncodeShared` buffer and nils the pointer. Nil-safe.
if not data.isNil():
c_free(data)
data = nil
proc cborDecode*[T](data: openArray[byte], _: typedesc[T]): Result[T, string] =
## Decode `data` into a `T`, mapping any exception to `Result.err`.
try:
let v = Cbor.decode(data, T)
return ok(v)
except CatchableError as exc:
return err(exc.msg)
proc cborDecodePtr*[T](
data: ptr UncheckedArray[byte], dataLen: int, _: typedesc[T]
): Result[T, string] =
## Convenience for ptr+len buffers.
if dataLen <= 0:
return cborDecode(default(seq[byte]), T)
cborDecode(toOpenArray(data, 0, dataLen - 1), T)