Skip to content

Commit 754f60a

Browse files
committed
refactor(cstr_stack): optimize CStrStack implementation to improve efficiency and reduce complexity
1 parent 2bac408 commit 754f60a

File tree

3 files changed

+14
-29
lines changed

3 files changed

+14
-29
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "stack-cstr"
3-
version = "0.1.1"
3+
version = "0.1.2"
44
edition = "2024"
55
authors = ["Junkang Yuan <[email protected]>"]
66
description = "High-performance stack-to-heap C string creation for Rust with FFI support"

src/cstr_stack.rs

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,11 @@ use arrayvec::ArrayString;
44

55
use crate::CStrLike;
66

7-
/// A stack-allocated C string with a fixed buffer size.
7+
/// A stack-allocated, null-terminated C string with fixed capacity.
88
///
9-
/// `CStrStack<N>` stores a formatted string directly on the stack
10-
/// with a buffer of `N` bytes, avoiding heap allocation.
11-
/// It always appends a trailing `\0` (null terminator) so it can be safely
12-
/// passed to C FFI functions.
13-
///
14-
/// If the formatted string (plus the null terminator) does not fit
15-
/// into the buffer, [`new`] will return an error.
9+
/// `CStrStack<N>` stores a formatted string directly on the stack, avoiding heap allocation.
10+
/// The internal buffer has `N` bytes and is always null-terminated (`\0`),
11+
/// making it safe to pass to C functions via `as_ptr()`.
1612
///
1713
/// # Examples
1814
///
@@ -34,14 +30,10 @@ use crate::CStrLike;
3430
///
3531
/// # Errors
3632
///
37-
/// Returns `Err("stack buffer overflow")` if the formatted string is too
38-
/// long to fit in the buffer.
39-
///
40-
/// Returns `Err("format failed")` if formatting the string fails
41-
/// (rare case, usually only if the formatter writes an error).
33+
/// - Returns `Err("buffer overflow")` if the formatted string (plus NUL) does not fit in the buffer.
34+
/// - Returns `Err("format failed")` if formatting fails (rare case; ArrayString rarely errors).
4235
pub struct CStrStack<const N: usize> {
43-
buf: [u8; N],
44-
len: usize,
36+
buf: ArrayString<N>,
4537
}
4638

4739
impl<const N: usize> CStrStack<N> {
@@ -53,19 +45,12 @@ impl<const N: usize> CStrStack<N> {
5345
let mut buf: ArrayString<N> = ArrayString::new();
5446
std::fmt::write(&mut buf, fmt).map_err(|_| "format failed")?;
5547

56-
let bytes = buf.as_bytes();
57-
if bytes.len() + 1 > N {
58-
return Err("stack buffer overflow");
48+
if buf.len() + 1 > N {
49+
return Err("buffer overflow");
5950
}
51+
buf.push('\0');
6052

61-
let mut c_buf: [u8; N] = [0; N];
62-
c_buf[..bytes.len()].copy_from_slice(bytes);
63-
c_buf[bytes.len()] = 0;
64-
65-
Ok(CStrStack {
66-
buf: c_buf,
67-
len: bytes.len(),
68-
})
53+
Ok(Self { buf })
6954
}
7055

7156
/// Returns a raw pointer to the null-terminated C string.
@@ -83,7 +68,7 @@ impl<const N: usize> CStrStack<N> {
8368
/// The buffer is guaranteed to be null-terminated by construction,
8469
/// so this is always safe.
8570
pub fn as_cstr(&self) -> &CStr {
86-
unsafe { CStr::from_bytes_with_nul_unchecked(&self.buf[..self.len + 1]) }
71+
unsafe { CStr::from_bytes_with_nul_unchecked(&self.buf.as_bytes()[..self.buf.len()]) }
8772
}
8873
}
8974

0 commit comments

Comments
 (0)