cstring_array/lib.rs
1// SPDX-FileCopyrightText: 2025 RAprogramm <andrey.rozanov.vl@gmail.com>
2//
3// SPDX-License-Identifier: MIT
4
5//! Safe, zero-copy wrapper for passing string arrays to C FFI (`char**`)
6//!
7//! This crate provides [`CStringArray`], a safe abstraction over C's
8//! null-terminated string arrays, commonly used for command-line arguments and
9//! similar purposes.
10//!
11//! # Features
12//!
13//! - **Memory-safe**: RAII-based lifetime management prevents dangling pointers
14//! - **Zero-copy**: When constructed from `Vec<CString>`, no re-allocation
15//! occurs
16//! - **C-compatible**: Produces valid `char**` pointers with null termination
17//! - **Ergonomic**: Multiple constructors and trait implementations for easy
18//! usage
19//! - **Well-tested**: Comprehensive test coverage for reliability
20//!
21//! # Example
22//!
23//! ```
24//! use std::ffi::c_char;
25//!
26//! use cstring_array::CStringArray;
27//!
28//! let args = vec![
29//! "program".to_string(),
30//! "--verbose".to_string(),
31//! "file.txt".to_string(),
32//! ];
33//! let array = CStringArray::new(args).unwrap();
34//!
35//! // Safe to pass to C FFI functions expecting char**
36//! let ptr: *const *const c_char = array.as_ptr();
37//! assert_eq!(array.len(), 3);
38//! ```
39//!
40//! # Creating Arrays
41//!
42//! Multiple ways to construct a `CStringArray`:
43//!
44//! ```
45//! use std::{convert::TryFrom, ffi::CString};
46//!
47//! use cstring_array::CStringArray;
48//!
49//! // From Vec<String>
50//! let arr1 = CStringArray::new(vec!["foo".to_string(), "bar".to_string()]).unwrap();
51//!
52//! // From Vec<CString> (zero-copy)
53//! let cstrings = vec![CString::new("foo").unwrap(), CString::new("bar").unwrap()];
54//! let arr2 = CStringArray::from_cstrings(cstrings).unwrap();
55//!
56//! // Using TryFrom with Vec<&str>
57//! let arr3 = CStringArray::try_from(vec!["foo", "bar"]).unwrap();
58//!
59//! // Using TryFrom with arrays
60//! let arr4 = CStringArray::try_from(["foo", "bar"]).unwrap();
61//! ```
62//!
63//! # Safety Considerations
64//!
65//! The pointer returned by [`CStringArray::as_ptr`] is only valid for the
66//! lifetime of the `CStringArray`. Ensure the array outlives any C code using
67//! the pointer:
68//!
69//! ```
70//! use std::ffi::c_char;
71//!
72//! use cstring_array::CStringArray;
73//!
74//! fn call_c_function(argv: *const *const c_char, argc: i32) {
75//! // ... FFI call ...
76//! }
77//!
78//! let array = CStringArray::new(vec!["arg1".to_string(), "arg2".to_string()]).unwrap();
79//! let ptr = array.as_ptr();
80//! call_c_function(ptr, array.len() as i32);
81//! // array must not be dropped before call_c_function returns
82//! ```
83
84mod array;
85mod error;
86mod traits;
87
88#[cfg(test)]
89mod tests;
90
91pub use array::CStringArray;
92pub use error::CStringArrayError;