From 812f7e74a6d245ee3164b7c1a894d89d66fb3257 Mon Sep 17 00:00:00 2001 From: Karl Stenerud Date: Mon, 22 Sep 2025 19:03:35 +0200 Subject: [PATCH] Move bd-bonjson's ffi functionality into a separate crate --- Cargo.lock | 17 +++++++ Cargo.toml | 1 + bd-bonjson-ffi/Cargo.toml | 25 +++++++++++ {bd-bonjson => bd-bonjson-ffi}/build.rs | 2 +- {bd-bonjson => bd-bonjson-ffi}/cbindgen.toml | 0 bd-bonjson-ffi/include/bd-bonjson/ffi.h | 45 +++++++++++++++++++ .../src/ffi.rs => bd-bonjson-ffi/src/lib.rs | 39 +++++++++++++--- bd-bonjson-tests/Cargo.toml | 3 +- bd-bonjson-tests/build.rs | 4 +- bd-bonjson-tests/src/ffi_tests.rs | 2 +- bd-bonjson/src/lib.rs | 1 - bd-bonjson/src/writer.rs | 5 +++ bd-bonjson/src/writer_test.rs | 2 +- 13 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 bd-bonjson-ffi/Cargo.toml rename {bd-bonjson => bd-bonjson-ffi}/build.rs (93%) rename {bd-bonjson => bd-bonjson-ffi}/cbindgen.toml (100%) create mode 100644 bd-bonjson-ffi/include/bd-bonjson/ffi.h rename bd-bonjson/src/ffi.rs => bd-bonjson-ffi/src/lib.rs (89%) diff --git a/Cargo.lock b/Cargo.lock index 1bc24ff4..af00c7b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -404,12 +404,29 @@ dependencies = [ "tempfile", ] +[[package]] +name = "bd-bonjson-ffi" +version = "1.0.0" +dependencies = [ + "assert_no_alloc", + "bd-bonjson", + "bd-test-helpers", + "bd-workspace-hack", + "bytes", + "cbindgen", + "ctor", + "libc", + "log", + "tempfile", +] + [[package]] name = "bd-bonjson-tests" version = "1.0.0" dependencies = [ "assert_no_alloc", "bd-bonjson", + "bd-bonjson-ffi", "bd-test-helpers", "bd-workspace-hack", "cc", diff --git a/Cargo.toml b/Cargo.toml index c2e66f80..b7caf363 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "bd-api", "bd-artifact-upload", "bd-bonjson", + "bd-bonjson-ffi", "bd-bonjson-tests", "bd-bounded-buffer", "bd-buffer", diff --git a/bd-bonjson-ffi/Cargo.toml b/bd-bonjson-ffi/Cargo.toml new file mode 100644 index 00000000..249756fd --- /dev/null +++ b/bd-bonjson-ffi/Cargo.toml @@ -0,0 +1,25 @@ +[package] +edition = "2024" +license-file = "../LICENSE" +name = "bd-bonjson-ffi" +publish = false +version = "1.0.0" + +[lib] +doctest = false + +[dev-dependencies] +assert_no_alloc.workspace = true +bd-test-helpers.path = "../bd-test-helpers" +ctor.workspace = true +tempfile.workspace = true + +[build-dependencies] +cbindgen.workspace = true + +[dependencies] +bd-bonjson.path = "../bd-bonjson" +bd-workspace-hack.workspace = true +bytes.workspace = true +libc.workspace = true +log.workspace = true diff --git a/bd-bonjson/build.rs b/bd-bonjson-ffi/build.rs similarity index 93% rename from bd-bonjson/build.rs rename to bd-bonjson-ffi/build.rs index de9d5b66..636131f6 100644 --- a/bd-bonjson/build.rs +++ b/bd-bonjson-ffi/build.rs @@ -13,7 +13,7 @@ pub fn main() { return; } - println!("cargo:rerun-if-changed=src/ffi.rs"); + println!("cargo:rerun-if-changed=src/lib.rs"); cbindgen::Builder::new() .with_crate(Path::new(".")) .with_config(Config::from_file(Path::new("cbindgen.toml")).unwrap()) diff --git a/bd-bonjson/cbindgen.toml b/bd-bonjson-ffi/cbindgen.toml similarity index 100% rename from bd-bonjson/cbindgen.toml rename to bd-bonjson-ffi/cbindgen.toml diff --git a/bd-bonjson-ffi/include/bd-bonjson/ffi.h b/bd-bonjson-ffi/include/bd-bonjson/ffi.h new file mode 100644 index 00000000..2f0c3e98 --- /dev/null +++ b/bd-bonjson-ffi/include/bd-bonjson/ffi.h @@ -0,0 +1,45 @@ +// shared-core - bitdrift's common client/server libraries +// Copyright Bitdrift, Inc. All rights reserved. +// +// Use of this source code is governed by a source available license that can be found in the +// LICENSE file or at: +// https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt + +#pragma once + +/* Warning: this file is autogenerated by cbindgen. Don't modify this manually. */ + +#include +#include +#include +#include + +typedef const void **BDCrashWriterHandle; + +/** + * Attempt to open a writer to the specified path. + * The writer exists on the heap and must be closed with `bdcrw_close_writer`. + */ +bool bdcrw_open_writer(BDCrashWriterHandle handle, const char *path); + +void bdcrw_close_writer(BDCrashWriterHandle handle); + +bool bdcrw_flush_writer(BDCrashWriterHandle handle); + +bool bdcrw_write_boolean(BDCrashWriterHandle handle, bool value); + +bool bdcrw_write_null(BDCrashWriterHandle handle); + +bool bdcrw_write_signed(BDCrashWriterHandle handle, int64_t value); + +bool bdcrw_write_unsigned(BDCrashWriterHandle handle, uint64_t value); + +bool bdcrw_write_float(BDCrashWriterHandle handle, double value); + +bool bdcrw_write_str(BDCrashWriterHandle handle, const char *value); + +bool bdcrw_write_array_begin(BDCrashWriterHandle handle); + +bool bdcrw_write_map_begin(BDCrashWriterHandle handle); + +bool bdcrw_write_container_end(BDCrashWriterHandle handle); diff --git a/bd-bonjson/src/ffi.rs b/bd-bonjson-ffi/src/lib.rs similarity index 89% rename from bd-bonjson/src/ffi.rs rename to bd-bonjson-ffi/src/lib.rs index bb129807..4b87aea6 100644 --- a/bd-bonjson/src/ffi.rs +++ b/bd-bonjson-ffi/src/lib.rs @@ -5,14 +5,45 @@ // LICENSE file or at: // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt -use crate::writer::Writer; +use bd_bonjson::writer::Writer; use std::ffi::c_void; use std::fs::{File, OpenOptions}; use std::io::{self, BufWriter, Write}; +use std::ops::{Deref, DerefMut}; use std::ptr::null; pub type BDCrashWriterHandle = *mut *const c_void; -pub type WriterBufWriterFile = Writer>; + +/// Newtype wrapper around `Writer>` to allow implementing traits +pub struct WriterBufWriterFile(Writer>); + +impl WriterBufWriterFile { + #[must_use] + pub fn new(writer: Writer>) -> Self { + Self(writer) + } + + #[must_use] + pub fn into_raw(self) -> *const c_void { + Box::into_raw(Box::new(self)) as *const c_void + } +} + +impl Deref for WriterBufWriterFile { + type Target = Writer>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for WriterBufWriterFile { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FFIError { @@ -58,9 +89,7 @@ fn new_writer(path: &str) -> io::Result { .write(true) .truncate(true) .open(path)?; - Ok(Writer { - writer: BufWriter::new(file), - }) + Ok(WriterBufWriterFile::new(Writer::new(BufWriter::new(file)))) } /// Attempt to open a writer to the specified path. diff --git a/bd-bonjson-tests/Cargo.toml b/bd-bonjson-tests/Cargo.toml index 6dddc41f..644d77dd 100644 --- a/bd-bonjson-tests/Cargo.toml +++ b/bd-bonjson-tests/Cargo.toml @@ -10,6 +10,7 @@ doctest = false [dependencies] bd-bonjson.path = "../bd-bonjson" +bd-bonjson-ffi.path = "../bd-bonjson-ffi" bd-workspace-hack.workspace = true libc.workspace = true @@ -19,5 +20,5 @@ bd-test-helpers.path = "../bd-test-helpers" tempfile.workspace = true [build-dependencies] -bd-bonjson.path = "../bd-bonjson" +bd-bonjson-ffi.path = "../bd-bonjson-ffi" cc.workspace = true diff --git a/bd-bonjson-tests/build.rs b/bd-bonjson-tests/build.rs index 883afdbd..ebbeb0a3 100644 --- a/bd-bonjson-tests/build.rs +++ b/bd-bonjson-tests/build.rs @@ -7,10 +7,10 @@ pub fn main() { println!("cargo:rerun-if-changed=src/ffi_tests.c"); - println!("cargo:rerun-if-changed=../bd-bonjson/src/ffi.rs"); + println!("cargo:rerun-if-changed=../bd-bonjson-ffi/src/lib.rs"); cc::Build::new() .cpp(false) .file("src/ffi_tests.c") - .include("../bd-bonjson/include") + .include("../bd-bonjson-ffi/include") .compile("bdbj"); } diff --git a/bd-bonjson-tests/src/ffi_tests.rs b/bd-bonjson-tests/src/ffi_tests.rs index 93e7e0f1..f339bd79 100644 --- a/bd-bonjson-tests/src/ffi_tests.rs +++ b/bd-bonjson-tests/src/ffi_tests.rs @@ -7,7 +7,7 @@ use assert_no_alloc::*; use bd_bonjson::Value; -use bd_bonjson::ffi::BDCrashWriterHandle; +use bd_bonjson_ffi::BDCrashWriterHandle; use std::ptr::null; use tempfile::NamedTempFile; diff --git a/bd-bonjson/src/lib.rs b/bd-bonjson/src/lib.rs index 377bfc1a..deea593d 100644 --- a/bd-bonjson/src/lib.rs +++ b/bd-bonjson/src/lib.rs @@ -16,7 +16,6 @@ pub mod decoder; pub mod encoder; -pub mod ffi; pub mod writer; mod deserialize_primitives; diff --git a/bd-bonjson/src/writer.rs b/bd-bonjson/src/writer.rs index 31aba969..6218ff92 100644 --- a/bd-bonjson/src/writer.rs +++ b/bd-bonjson/src/writer.rs @@ -19,6 +19,11 @@ pub struct Writer { } impl Writer { + /// Create a new Writer with the given underlying writer + pub fn new(writer: W) -> Self { + Self { writer } + } + #[must_use] pub fn into_raw(self) -> *const c_void { Box::into_raw(Box::new(self)) as *const _ diff --git a/bd-bonjson/src/writer_test.rs b/bd-bonjson/src/writer_test.rs index 1018d6c5..c2bb7d17 100644 --- a/bd-bonjson/src/writer_test.rs +++ b/bd-bonjson/src/writer_test.rs @@ -66,7 +66,7 @@ fn writer_does_not_allocate_writing_to_file() { // Use BufWriter to avoid frequent system calls let buf_writer = Box::new(BufWriter::new(file)); - let mut writer = Writer { writer: buf_writer }; + let mut writer = Writer::new(buf_writer); assert_no_alloc(|| { for _ in 0 .. 100_000 {