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}