stack_cstr/
cstr_stack.rs

1use std::ffi::{CStr, c_char};
2
3use arrayvec::ArrayString;
4
5use crate::CStrLike;
6
7pub struct CStrStack<const N: usize> {
8    buf: [u8; N],
9    len: usize,
10}
11
12impl<const N: usize> CStrStack<N> {
13    pub fn new(fmt: std::fmt::Arguments) -> Result<CStrStack<N>, &'static str> {
14        let mut buf: ArrayString<N> = ArrayString::new();
15        std::fmt::write(&mut buf, fmt).map_err(|_| "format failed")?;
16
17        let bytes = buf.as_bytes();
18        if bytes.len() + 1 > N {
19            return Err("stack buffer overflow");
20        }
21
22        let mut c_buf: [u8; N] = [0; N];
23        c_buf[..bytes.len()].copy_from_slice(bytes);
24        c_buf[bytes.len()] = 0;
25
26        Ok(CStrStack {
27            buf: c_buf,
28            len: bytes.len(),
29        })
30    }
31
32    pub fn as_ptr(&self) -> *const c_char {
33        self.buf.as_ptr() as *const c_char
34    }
35
36    pub fn as_cstr(&self) -> &CStr {
37        unsafe { CStr::from_bytes_with_nul_unchecked(&self.buf[..self.len + 1]) }
38    }
39}
40
41impl<const N: usize> CStrLike for CStrStack<N> {
42    fn as_ptr(&self) -> *const c_char {
43        self.as_ptr()
44    }
45
46    fn as_cstr(&self) -> &CStr {
47        self.as_cstr()
48    }
49}