lwprintf_rs/
lib.rs

1//! LwPRINTF Rust bindings and wrappers.
2//!
3#![no_std]
4#![feature(c_variadic)]
5#![deny(missing_docs)]
6#![allow(
7    non_snake_case,
8    non_camel_case_types,
9    non_upper_case_globals,
10    clashing_extern_declarations
11)]
12
13mod bindings {
14    #![allow(unused)]
15    include!(concat!(env!("OUT_DIR"), "/lwprintf.rs"));
16}
17use core::ptr::null_mut;
18
19use bindings::lwprintf_t;
20
21/// Maximum size value for buffers.
22pub const SIZE_MAX: i32 = bindings::SIZE_MAX as _;
23
24/// Trait for custom output handling.
25pub trait CustomOutPut {
26    /// Output a single character.
27    fn putch(ch: i32) -> i32;
28}
29
30/// LwPRINTF object with custom output handler.
31pub struct LwprintfObj<T: CustomOutPut> {
32    obj: lwprintf_t,
33    _phantom: core::marker::PhantomData<T>,
34}
35
36impl<T: CustomOutPut> Default for LwprintfObj<T> {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42impl<T: CustomOutPut> LwprintfObj<T> {
43    /// Create a new uninitialized LwPRINTF object.
44    pub fn new() -> Self {
45        let obj = lwprintf_t {
46            out_fn: None,
47            arg: core::ptr::null_mut(),
48        };
49
50        Self {
51            obj,
52            _phantom: core::marker::PhantomData,
53        }
54    }
55
56    /// Get a mutable reference to the underlying lwprintf_t object.
57    ///
58    /// This allows calling sys functions directly with the object.
59    pub fn as_mut_ptr(&mut self) -> *mut lwprintf_t {
60        &mut self.obj
61    }
62}
63
64extern "C" fn out_fn<T: CustomOutPut>(
65    ch: core::ffi::c_int,
66    _lwobj: *mut lwprintf_t,
67) -> core::ffi::c_int {
68    T::putch(ch)
69}
70
71/// Initialize lwprintf object with custom output function.
72pub fn lwprintf_init_ex<T: CustomOutPut>(lwobj: &mut LwprintfObj<T>) -> u8 {
73    unsafe { bindings::lwprintf_init_ex(lwobj.as_mut_ptr(), Some(out_fn::<T>)) }
74}
75
76/// Initialize default lwprintf instance.
77pub fn lwprintf_init<T: CustomOutPut>() -> u8 {
78    unsafe { bindings::lwprintf_init_ex(null_mut(), Some(out_fn::<T>)) }
79}
80
81mod sys_inner {
82    use core::ffi::VaList;
83
84    use crate::bindings::lwprintf_t;
85
86    unsafe extern "C" {
87        /// Print formatted data from variable argument list to the output.
88        /// # Arguments
89        /// * `lwobj` - LwPRINTF instance. Set to NULL to use default instance.
90        /// * `format` - C string that contains the text to be written to output.
91        /// * `arg` - A value identifying a variable arguments list initialized with va_start. va_list is a special type defined in cstdarg.
92        pub fn lwprintf_vprintf_ex(
93            lwobj: *mut lwprintf_t,
94            format: *const core::ffi::c_char,
95            arg: VaList,
96        ) -> core::ffi::c_int;
97
98        /// Write formatted data from variable argument list to sized buffer.
99        /// # Arguments
100        /// * `lwobj` - LwPRINTF instance. Set to NULL to use default instance.
101        /// * `s` - Pointer to a buffer where the resulting C-string is stored. The buffer should have a size of at least n characters.
102        /// * `n` - Maximum number of bytes to be used in the buffer. The generated string has a length of at most n - 1, leaving space for the additional terminating null character.
103        /// * `format` - C string that contains the text to be written to output.
104        /// * `arg` - A value identifying a variable arguments list initialized with va_start. va_list is a special type defined in cstdarg.
105        pub fn lwprintf_vsnprintf_ex(
106            lwobj: *mut lwprintf_t,
107            s: *mut core::ffi::c_char,
108            n: usize,
109            format: *const core::ffi::c_char,
110            arg: VaList,
111        ) -> core::ffi::c_int;
112
113        /// Print formatted data to the output.
114        /// # Arguments
115        /// * `lwobj` - LwPRINTF instance. Set to NULL to use default instance.
116        /// * `format` - C string that contains the text to be written to output.
117        /// * `...` -  Optional arguments for format string.
118        pub fn lwprintf_printf_ex(
119            lwobj: *mut lwprintf_t,
120            format: *const core::ffi::c_char,
121            ...
122        ) -> core::ffi::c_int;
123
124        /// Write formatted data from variable argument list to sized buffer.
125        /// # Arguments
126        /// * `lwobj` - LwPRINTF instance. Set to NULL to use default instance.
127        /// * `s` - Pointer to a buffer where the resulting C-string is stored. The buffer should have a size of at least n characters.
128        /// * `n` - Maximum number of bytes to be used in the buffer. The generated string has a length of at most n - 1, leaving space for the additional terminating null character.
129        /// * `format` - C string that contains a format string that follows the same specifications as format in printf.
130        /// * `...` -  Optional arguments for format string.
131        /// # Returns
132        /// The number of characters that would have been written if n had been sufficiently large, not counting the terminating null character.
133        pub fn lwprintf_snprintf_ex(
134            lwobj: *mut lwprintf_t,
135            s: *mut ::core::ffi::c_char,
136            n: usize,
137            format: *const ::core::ffi::c_char,
138            ...
139        ) -> ::core::ffi::c_int;
140    }
141}
142
143pub use sys_inner::lwprintf_printf_ex;
144pub use sys_inner::lwprintf_snprintf_ex;
145pub use sys_inner::lwprintf_vprintf_ex;
146pub use sys_inner::lwprintf_vsnprintf_ex;
147
148/// Print formatted data from variable argument list to the output.
149///
150/// **WARNING**: This function is an wrapper for [lwprintf_vprintf_ex] and uses Rust's
151/// variadic arguments feature. If you plan to call this function from C code or need
152/// precise control over the `va_list`, use [lwprintf_vprintf_ex] directly.
153///
154/// # Arguments
155/// * `args` - Additional arguments specifying data to print.
156/// * other arguments are the same as [lwprintf_vprintf_ex].
157///
158/// # Safety
159/// This function is unsafe because it uses C-style variadic arguments.
160pub unsafe extern "C" fn lwprintf_vprintf_ex_rust(
161    lwobj: *mut lwprintf_t,
162    fmt: *const core::ffi::c_char,
163    mut args: ...
164) -> core::ffi::c_int {
165    unsafe { sys_inner::lwprintf_vprintf_ex(lwobj, fmt, args.as_va_list()) }
166}
167
168/// Write formatted data from variable argument list to sized buffer.
169///
170/// **WARNING**: This function is an wrapper for [lwprintf_vsnprintf_ex] and uses Rust's
171/// variadic arguments feature. If you plan to call this function from C code or need
172/// precise control over the `va_list`, use [lwprintf_vsnprintf_ex] directly
173/// # Arguments
174/// * `args` - Additional arguments specifying data to print.
175/// * other arguments are the same as [lwprintf_vsnprintf_ex].
176///
177/// # Safety
178/// This function is unsafe because it uses C-style variadic arguments.
179pub unsafe extern "C" fn lwprintf_vsnprintf_ex_rust(
180    lwobj: *mut lwprintf_t,
181    s: *mut core::ffi::c_char,
182    n: usize,
183    fmt: *const core::ffi::c_char,
184    mut args: ...
185) -> core::ffi::c_int {
186    unsafe { sys_inner::lwprintf_vsnprintf_ex(lwobj, s, n, fmt, args.as_va_list()) }
187}
188
189/// Write formatted data from variable argument list to sized buffer.
190/// This macro uses [lwprintf_snprintf_ex] internally with `n` set to `SIZE_MAX`.
191///
192/// **WARNING:** User is responsible for ensuring that the buffer is large enough to hold the formatted string.
193#[macro_export]
194macro_rules! lwprintf_sprintf_ex {
195    ( $lwobj:expr, $buf:expr, $format:expr, $( $args:expr ),* ) => {
196        unsafe {
197            $crate::lwprintf_snprintf_ex(
198                $lwobj,
199                $buf,
200                $crate::SIZE_MAX as usize,
201                $format,
202                $( $args ),*
203            )
204        }
205    };
206}
207
208/// Print formatted data from variable argument list to the output with default LwPRINTF instance.
209/// This macro uses [lwprintf_vprintf_ex] internally with `lwobj` set to NULL.
210#[macro_export]
211macro_rules! lwprintf_vprintf {
212    ( $format:expr, $arg: expr ) => {
213        unsafe { $crate::lwprintf_vprintf_ex(core::ptr::null_mut(), $format, $arg) }
214    };
215}
216
217/// Print formatted data to the output with default LwPRINTF instance.
218///
219/// This macro uses [lwprintf_printf_ex] internally with `lwobj` set to NULL.
220#[macro_export]
221macro_rules! lwprintf_printf {
222    ($format:expr, $( $args:expr ),* ) => {
223        unsafe {
224            $crate::lwprintf_printf_ex(
225                core::ptr::null_mut(),
226                $format,
227                $( $args ),*
228            )
229        }
230    };
231}
232
233/// Write formatted data from variable argument list to sized buffer with default LwPRINTF instance.
234///
235/// This macro uses [lwprintf_vsnprintf_ex] internally with `lwobj` set to NULL.
236#[macro_export]
237macro_rules! lwprintf_vsnprintf {
238    ( $buf:expr, $n:expr, $format:expr, $arg: expr ) => {
239        unsafe { $crate::lwprintf_vsnprintf_ex(core::ptr::null_mut(), $buf, $n, $format, $arg) }
240    };
241}
242
243/// Write formatted data to sized buffer with default LwPRINTF instance.
244///
245/// This macro uses [lwprintf_snprintf_ex] internally with `lwobj` set to NULL.
246#[macro_export]
247macro_rules! lwprintf_snprintf {
248    ( $buf:expr, $n:expr, $format:expr, $( $args:expr ),* ) => {
249        unsafe {
250            $crate::lwprintf_snprintf_ex(
251                core::ptr::null_mut(),
252                $buf,
253                $n,
254                $format,
255                $( $args ),*
256            )
257        }
258    };
259}
260
261/// Write formatted data from variable argument list to sized buffer with default LwPRINTF instance.
262///
263/// This macro uses [lwprintf_snprintf_ex] internally with `lwobj` set to NULL and `n` set to `SIZE_MAX`.
264#[macro_export]
265macro_rules! lwprintf_sprintf {
266    ($buf:expr, $format:expr, $( $args:expr ),* ) => {
267        unsafe {
268            $crate::lwprintf_sprintf_ex!(core::ptr::null_mut(), $buf, $format, $( $args ),* )
269        }
270    };
271}