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}