feat: delete redundant box in cstr_ffi module
This commit is contained in:
+42
-21
@@ -106,11 +106,13 @@ pub type CStrViewVecPtr = *const CStringView;
|
||||
|
||||
/// One independent string-vector slot.
|
||||
///
|
||||
/// `items` owns the actual `CString` data, each individually boxed so the pointers stay stable
|
||||
/// even when `items` grows. `ptrs` is the parallel pointer array consumed by C/C++; for the
|
||||
/// nullptr-terminated variant a trailing null pointer is appended to `ptrs`.
|
||||
/// `items` owns the actual `CString` data. Each `CString`'s backing buffer is an independent heap
|
||||
/// allocation, so the `CStrPtr` values captured in `ptrs` stay stable even when `items` (or the
|
||||
/// containing cache) reallocates and merely moves the `CString` headers. `ptrs` is the parallel
|
||||
/// pointer array consumed by C/C++; a trailing null pointer is appended for the
|
||||
/// nullptr-terminated form.
|
||||
struct CStringVec {
|
||||
items: Vec<Box<CString>>,
|
||||
items: Vec<CString>,
|
||||
ptrs: Vec<CStrPtr>,
|
||||
}
|
||||
|
||||
@@ -133,9 +135,9 @@ impl CStringVec {
|
||||
ptrs: Vec::with_capacity(ptrs_cap),
|
||||
};
|
||||
for s in items {
|
||||
let boxed = Box::new(CString::new(*s)?);
|
||||
obj.ptrs.push(boxed.as_ptr());
|
||||
obj.items.push(boxed);
|
||||
let cs = CString::new(*s)?;
|
||||
obj.ptrs.push(cs.as_ptr());
|
||||
obj.items.push(cs);
|
||||
}
|
||||
obj.ptrs.push(std::ptr::null());
|
||||
Ok(obj)
|
||||
@@ -185,10 +187,29 @@ impl CStringViewVec {
|
||||
}
|
||||
}
|
||||
|
||||
/// The thread-local container that owns every output slot produced during a single FFI call.
|
||||
///
|
||||
/// It holds three independent groups of slots, each of which may accumulate an arbitrary number of
|
||||
/// entries across one call:
|
||||
///
|
||||
/// - `strings`: individual NUL-terminated strings produced by [`push_ffi_string`].
|
||||
/// - `string_vecs`: string-vector slots produced by [`push_ffi_string_vec`] /
|
||||
/// [`push_ffi_string_vec_with_len`].
|
||||
/// - `string_view_vecs`: string-view-vector containers produced by
|
||||
/// [`push_ffi_string_view_vec_with_len`]; only the container is owned here, the viewed string
|
||||
/// data stays caller-owned.
|
||||
///
|
||||
/// # Pointer stability
|
||||
///
|
||||
/// The slots are stored directly (not boxed). Each slot's exposed pointer -- a [`CStrPtr`] for a
|
||||
/// `CString`, the head of `ptrs` for a `CStringVec`, or the head of `views` for a
|
||||
/// `CStringViewVec` -- addresses an independent heap allocation. Reallocating any of these `Vec`s
|
||||
/// only moves the owning headers; the heap buffers behind those pointers stay put, so every
|
||||
/// pointer already handed to C/C++ remains valid until [`StringCache::clear`] is called.
|
||||
struct StringCache {
|
||||
strings: Vec<Box<CString>>,
|
||||
string_vecs: Vec<Box<CStringVec>>,
|
||||
string_view_vecs: Vec<Box<CStringViewVec>>,
|
||||
strings: Vec<CString>,
|
||||
string_vecs: Vec<CStringVec>,
|
||||
string_view_vecs: Vec<CStringViewVec>,
|
||||
}
|
||||
|
||||
impl StringCache {
|
||||
@@ -210,20 +231,20 @@ impl StringCache {
|
||||
self.string_view_vecs.clear();
|
||||
}
|
||||
|
||||
/// Store one boxed NUL-terminated string and return its stable pointer.
|
||||
fn push_string(&mut self, s: Box<CString>) -> CStrPtr {
|
||||
/// Store one NUL-terminated string and return its stable pointer.
|
||||
fn push_string(&mut self, s: CString) -> CStrPtr {
|
||||
let ptr = s.as_ptr();
|
||||
self.strings.push(s);
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Store one boxed string-vector slot.
|
||||
fn push_string_vec(&mut self, sv: Box<CStringVec>) {
|
||||
/// Store one string-vector slot.
|
||||
fn push_string_vec(&mut self, sv: CStringVec) {
|
||||
self.string_vecs.push(sv);
|
||||
}
|
||||
|
||||
/// Store one boxed string-view-vector slot.
|
||||
fn push_string_view_vec(&mut self, svv: Box<CStringViewVec>) {
|
||||
/// Store one string-view-vector slot.
|
||||
fn push_string_view_vec(&mut self, svv: CStringViewVec) {
|
||||
self.string_view_vecs.push(svv);
|
||||
}
|
||||
}
|
||||
@@ -258,8 +279,8 @@ pub fn clear_ffi_strings() {
|
||||
///
|
||||
/// Returns an error if `s` contains an interior NUL byte.
|
||||
pub fn push_ffi_string(s: &str) -> Result<CStrPtr> {
|
||||
let boxed = Box::new(CString::new(s)?);
|
||||
STRING_CACHE.with(|c| Ok(c.borrow_mut().push_string(boxed)))
|
||||
let cs = CString::new(s)?;
|
||||
STRING_CACHE.with(|c| Ok(c.borrow_mut().push_string(cs)))
|
||||
}
|
||||
|
||||
/// Push one independent string vector (NUL-terminated entries, **nullptr-terminated list**) into
|
||||
@@ -276,7 +297,7 @@ pub fn push_ffi_string(s: &str) -> Result<CStrPtr> {
|
||||
///
|
||||
/// Returns an error if any entry contains an interior NUL byte.
|
||||
pub fn push_ffi_string_vec(items: &[&str]) -> Result<CStrVecPtr> {
|
||||
let sv = Box::new(CStringVec::new(items)?);
|
||||
let sv = CStringVec::new(items)?;
|
||||
let head = sv.head_ptr();
|
||||
STRING_CACHE.with(|c| c.borrow_mut().push_string_vec(sv));
|
||||
Ok(head)
|
||||
@@ -298,7 +319,7 @@ pub fn push_ffi_string_vec(items: &[&str]) -> Result<CStrVecPtr> {
|
||||
///
|
||||
/// Returns an error if any entry contains an interior NUL byte.
|
||||
pub fn push_ffi_string_vec_with_len(items: &[&str]) -> Result<(CStrVecPtr, usize)> {
|
||||
let sv = Box::new(CStringVec::new(items)?);
|
||||
let sv = CStringVec::new(items)?;
|
||||
let head = sv.head_ptr();
|
||||
let count = sv.item_count();
|
||||
STRING_CACHE.with(|c| c.borrow_mut().push_string_vec(sv));
|
||||
@@ -347,7 +368,7 @@ pub fn push_ffi_string_view(s: &str) -> (CStrPtr, usize) {
|
||||
/// reads (per `Vec::as_ptr` for an empty allocation). The foreign side must drive consumption off
|
||||
/// `count` and must not dereference the pointer when `count` is 0.
|
||||
pub fn push_ffi_string_view_vec_with_len(items: &[&str]) -> (CStrViewVecPtr, usize) {
|
||||
let svv = Box::new(CStringViewVec::new(items));
|
||||
let svv = CStringViewVec::new(items);
|
||||
let head = svv.head_ptr();
|
||||
let count = svv.item_count();
|
||||
STRING_CACHE.with(|c| c.borrow_mut().push_string_view_vec(svv));
|
||||
|
||||
Reference in New Issue
Block a user