stack_cstr/
cstr_heap.rs

1use std::ffi::{CStr, CString, c_char};
2
3use crate::CStrLike;
4
5/// A heap-allocated C-compatible string wrapper.
6///
7/// `CStrHeap` owns a [`CString`] internally, and implements the
8/// [`CStrLike`] trait to provide a uniform interface with
9/// stack-allocated alternatives (e.g. `CStrStack`).
10///
11/// This is used as a fallback when the string cannot fit into
12/// a fixed-size stack buffer.
13pub struct CStrHeap {
14    cstr: CString,
15}
16
17impl CStrHeap {
18    /// Creates a new `CStrHeap` from a given [`CString`].
19    ///
20    /// # Arguments
21    ///
22    /// * `s` - A [`CString`] instance to be wrapped.
23    ///
24    /// # Examples
25    ///
26    /// ```
27    /// use std::ffi::CString;
28    /// use stack_cstr::CStrHeap;
29    ///
30    /// let cstr = CString::new("hello").unwrap();
31    /// let heap = CStrHeap::new(cstr);
32    /// assert_eq!(unsafe { std::ffi::CStr::from_ptr(heap.as_ptr()) }.to_str().unwrap(), "hello");
33    /// ```
34    pub fn new(s: CString) -> Self {
35        Self { cstr: s }
36    }
37
38    /// Returns a raw pointer to the underlying C string.
39    ///
40    /// The pointer is guaranteed to be valid as long as the `CStrHeap`
41    /// instance is alive. The string is null-terminated.
42    pub fn as_ptr(&self) -> *const c_char {
43        self.cstr.as_ptr()
44    }
45
46    /// Returns a reference to the underlying [`CStr`].
47    ///
48    /// # Examples
49    ///
50    /// ```
51    /// use std::ffi::CString;
52    /// use stack_cstr::CStrHeap;
53    ///
54    /// let cstr = CString::new("hello").unwrap();
55    /// let heap = CStrHeap::new(cstr);
56    /// let slice = heap.as_cstr();
57    /// assert_eq!(slice.to_str().unwrap(), "hello");
58    /// ```
59    pub fn as_cstr(&self) -> &CStr {
60        self.cstr.as_c_str()
61    }
62}
63
64impl CStrLike for CStrHeap {
65    fn as_ptr(&self) -> *const c_char {
66        self.as_ptr()
67    }
68
69    fn as_cstr(&self) -> &CStr {
70        self.as_cstr()
71    }
72}