// ── encode_cbor overloads (primitives + containers) ───────────────────── // Per-struct encode_cbor / decode_cbor are emitted by cpp.nim next to each // generated struct; these helpers cover the leaf types they defer into. // Guarded so two nim-ffi headers can share a translation unit. #ifndef NIM_FFI_CBOR_HELPERS_HPP_INCLUDED #define NIM_FFI_CBOR_HELPERS_HPP_INCLUDED inline CborError encode_cbor(CborEncoder& e, bool v) { return cbor_encode_boolean(&e, v); } inline CborError encode_cbor(CborEncoder& e, int64_t v) { return cbor_encode_int(&e, v); } inline CborError encode_cbor(CborEncoder& e, int32_t v) { return cbor_encode_int(&e, static_cast(v)); } inline CborError encode_cbor(CborEncoder& e, uint64_t v) { return cbor_encode_uint(&e, v); } inline CborError encode_cbor(CborEncoder& e, double v) { return cbor_encode_double(&e, v); } inline CborError encode_cbor(CborEncoder& e, const std::string& v) { return cbor_encode_text_string(&e, v.data(), v.size()); } template inline CborError encode_cbor(CborEncoder& e, const std::vector& v) { CborEncoder arr; CborError err = cbor_encoder_create_array(&e, &arr, v.size()); if (err) return err; for (const auto& item : v) { err = encode_cbor(arr, item); if (err) return err; } return cbor_encoder_close_container(&e, &arr); } template inline CborError encode_cbor(CborEncoder& e, const std::optional& v) { if (!v) return cbor_encode_null(&e); return encode_cbor(e, *v); } // ── decode_cbor overloads ─────────────────────────────────────────────── inline CborError decode_cbor(CborValue& it, bool& out) { if (!cbor_value_is_boolean(&it)) return CborErrorImproperValue; CborError err = cbor_value_get_boolean(&it, &out); if (err) return err; return cbor_value_advance(&it); } inline CborError decode_cbor(CborValue& it, int64_t& out) { if (!cbor_value_is_integer(&it)) return CborErrorImproperValue; CborError err = cbor_value_get_int64_checked(&it, &out); if (err) return err; return cbor_value_advance(&it); } inline CborError decode_cbor(CborValue& it, int32_t& out) { int64_t tmp = 0; CborError err = decode_cbor(it, tmp); if (err) return err; out = static_cast(tmp); return CborNoError; } inline CborError decode_cbor(CborValue& it, uint64_t& out) { if (!cbor_value_is_unsigned_integer(&it)) return CborErrorImproperValue; CborError err = cbor_value_get_uint64(&it, &out); if (err) return err; return cbor_value_advance(&it); } inline CborError decode_cbor(CborValue& it, double& out) { if (cbor_value_is_double(&it)) { CborError err = cbor_value_get_double(&it, &out); if (err) return err; return cbor_value_advance(&it); } if (cbor_value_is_float(&it)) { float f = 0.0f; CborError err = cbor_value_get_float(&it, &f); if (err) return err; out = static_cast(f); return cbor_value_advance(&it); } return CborErrorImproperValue; } inline CborError decode_cbor(CborValue& it, std::string& out) { if (!cbor_value_is_text_string(&it)) return CborErrorImproperValue; size_t len = 0; CborError err = cbor_value_get_string_length(&it, &len); if (err) return err; out.resize(len); err = cbor_value_copy_text_string(&it, out.empty() ? nullptr : &out[0], &len, nullptr); if (err) return err; return cbor_value_advance(&it); } template inline CborError decode_cbor(CborValue& it, std::vector& out) { if (!cbor_value_is_array(&it)) return CborErrorImproperValue; size_t len = 0; CborError err = cbor_value_get_array_length(&it, &len); if (err) return err; out.clear(); out.resize(len); CborValue inner; err = cbor_value_enter_container(&it, &inner); if (err) return err; for (size_t i = 0; i < len; ++i) { err = decode_cbor(inner, out[i]); if (err) return err; } return cbor_value_leave_container(&it, &inner); } template inline CborError decode_cbor(CborValue& it, std::optional& out) { if (cbor_value_is_null(&it)) { out = std::nullopt; return cbor_value_advance(&it); } T tmp{}; CborError err = decode_cbor(it, tmp); if (err) return err; out = std::move(tmp); return CborNoError; } // ── Public entry points ───────────────────────────────────────────────── template inline Result> encodeCborFFI(const T& value) { // Start with a generous 4 KiB buffer; double on overflow until it fits. std::vector buf(4096); while (true) { CborEncoder enc; cbor_encoder_init(&enc, buf.data(), buf.size(), 0); CborError err = encode_cbor(enc, value); if (err == CborNoError) { const size_t used = cbor_encoder_get_buffer_size(&enc, buf.data()); buf.resize(used); return Result>::ok(std::move(buf)); } if (err == CborErrorOutOfMemory) { const size_t extra = cbor_encoder_get_extra_bytes_needed(&enc); buf.resize(buf.size() + (extra > 0 ? extra : buf.size())); continue; } return Result>::err( std::string("FFI CBOR encode failed: ") + cbor_error_string(err)); } } template inline Result decodeCborFFI(const std::vector& bytes) { CborParser parser; CborValue it; CborError err = cbor_parser_init(bytes.data(), bytes.size(), 0, &parser, &it); if (err != CborNoError) { return Result::err(std::string("FFI CBOR parse init failed: ") + cbor_error_string(err)); } T out{}; err = decode_cbor(it, out); if (err != CborNoError) { return Result::err(std::string("FFI CBOR decode failed: ") + cbor_error_string(err)); } return Result::ok(std::move(out)); } #endif // NIM_FFI_CBOR_HELPERS_HPP_INCLUDED