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}