|
| 1 | +//! # stack_cstr |
| 2 | +//! |
| 3 | +//! `stack_cstr` provides ergonomic and efficient ways to create |
| 4 | +//! [`CStr`](std::ffi::CStr) values for FFI interoperability. |
| 5 | +//! |
| 6 | +//! The crate offers both **stack-based** and **heap-based** strategies |
| 7 | +//! for storing C-compatible strings. Its goal is to minimize heap |
| 8 | +//! allocations for short-lived or short strings while providing |
| 9 | +//! automatic fallback to the heap when needed. |
| 10 | +//! |
| 11 | +//! ## Motivation |
| 12 | +//! |
| 13 | +//! When interacting with C APIs, strings must be passed as |
| 14 | +//! null-terminated `*const c_char`. The standard way in Rust |
| 15 | +//! is to use [`CString`], which always allocates on the heap. |
| 16 | +//! |
| 17 | +//! However, in performance-sensitive or embedded environments, |
| 18 | +//! frequent heap allocations are undesirable. `stack_cstr` allows |
| 19 | +//! you to create `CStr` objects backed by **fixed-size stack buffers**, |
| 20 | +//! avoiding heap allocations for common short strings. |
| 21 | +//! |
| 22 | +//! ## Core Components |
| 23 | +//! |
| 24 | +//! - [`CStrLike`](crate::CStrLike): A trait for types that can expose |
| 25 | +//! a `*const c_char` and a `&CStr`. |
| 26 | +//! - [`CStrStack`](crate::CStrStack): A stack-allocated C string with |
| 27 | +//! a user-defined capacity. |
| 28 | +//! - [`CStrHeap`](crate::CStrHeap): A heap-allocated C string wrapper |
| 29 | +//! around [`CString`]. |
| 30 | +//! - [`cstr!`](crate::cstr): A macro that automatically chooses between |
| 31 | +//! stack or heap storage depending on the string length. |
| 32 | +//! |
| 33 | +//! ## Example: Using the `cstr!` Macro |
| 34 | +//! |
| 35 | +//! ``` |
| 36 | +//! use std::ffi::CStr; |
| 37 | +//! use stack_cstr::{cstr, CStrLike}; |
| 38 | +//! |
| 39 | +//! // Default stack sizes are [32, 128] |
| 40 | +//! let s = cstr!("Hello {}", 42); |
| 41 | +//! assert_eq!(s.as_cstr().to_str().unwrap(), "Hello 42"); |
| 42 | +//! |
| 43 | +//! // Explicitly set candidate stack buffer sizes |
| 44 | +//! let s = cstr!([16, 64], "Pi = {:.2}", 3.14159); |
| 45 | +//! assert_eq!(s.as_cstr().to_str().unwrap(), "Pi = 3.14"); |
| 46 | +//! |
| 47 | +//! unsafe { |
| 48 | +//! // Pass to FFI as *const c_char |
| 49 | +//! let ptr = s.as_ptr(); |
| 50 | +//! assert_eq!(CStr::from_ptr(ptr).to_str().unwrap(), "Pi = 3.14"); |
| 51 | +//! } |
| 52 | +//! ``` |
| 53 | +//! |
| 54 | +//! ## Example: Manual Use of `CStrStack` |
| 55 | +//! |
| 56 | +//! ``` |
| 57 | +//! use stack_cstr::CStrStack; |
| 58 | +//! |
| 59 | +//! // Create a stack-allocated C string with capacity 32 |
| 60 | +//! let s = CStrStack::<32>::new(format_args!("ABC {}!", 123)).unwrap(); |
| 61 | +//! assert_eq!(s.as_cstr().to_str().unwrap(), "ABC 123!"); |
| 62 | +//! ``` |
| 63 | +//! |
| 64 | +//! ## Example: Manual Use of `CStrHeap` |
| 65 | +//! |
| 66 | +//! ``` |
| 67 | +//! use std::ffi::CString; |
| 68 | +//! use stack_cstr::CStrHeap; |
| 69 | +//! |
| 70 | +//! let heap_str = CStrHeap::new(CString::new("Hello from heap").unwrap()); |
| 71 | +//! assert_eq!(heap_str.as_cstr().to_str().unwrap(), "Hello from heap"); |
| 72 | +//! ``` |
| 73 | +//! |
| 74 | +//! ## Design Notes |
| 75 | +//! |
| 76 | +//! - `CStrStack` checks buffer boundaries at construction time and |
| 77 | +//! guarantees proper null termination. |
| 78 | +//! - `cstr!` hides the complexity by trying multiple stack sizes and |
| 79 | +//! falling back to heap when necessary. |
| 80 | +//! - Returned values from `cstr!` are `Box<dyn CStrLike>` for uniformity, |
| 81 | +//! even when stack-backed. This introduces a single heap allocation |
| 82 | +//! for type erasure, which is usually negligible compared to string allocation. |
| 83 | +//! |
| 84 | +//! ## Use Cases |
| 85 | +//! |
| 86 | +//! - Embedding short strings in FFI calls without heap allocation. |
| 87 | +//! - Performance-sensitive applications where allocation patterns matter. |
| 88 | +//! - Embedded systems where heap memory is constrained. |
| 89 | +//! |
| 90 | +//! ## Limitations |
| 91 | +//! |
| 92 | +//! - `CStrStack` requires a compile-time constant buffer size. |
| 93 | +//! - Even stack-backed strings returned from `cstr!` are wrapped in a `Box` |
| 94 | +//! to allow dynamic dispatch. |
| 95 | +//! |
| 96 | +//! ## See Also |
| 97 | +//! |
| 98 | +//! - [`CString`](std::ffi::CString) for heap-allocated C strings |
| 99 | +//! - [`CStr`](std::ffi::CStr) for borrowed C strings |
| 100 | +//! - [`arrayvec`](https://docs.rs/arrayvec) used internally for formatting |
| 101 | +
|
1 | 102 | pub mod cstr_heap; |
2 | 103 | pub mod cstr_like; |
3 | 104 | pub mod cstr_stack; |
|
0 commit comments