printf_wrap/
printf_arg_impls.rs

1// Copyright (c) 2021-2023 The Pennsylvania State University and the project contributors.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Implementations of [`PrintfArgument`] and allied traits.
5
6use crate::{is_compat, LargerOf, NullString};
7use crate::{PrintfArgument, PrintfArgumentPrivate};
8
9use core::ffi::{c_char, c_double, c_int, c_uint, c_void, CStr};
10
11macro_rules! impl_empty_trait {
12    ($trait_name:ident ; $($implementor:ty),*) => {
13        $(
14            impl $trait_name for $implementor { }
15        )*
16    };
17}
18
19impl_empty_trait!(PrintfArgumentPrivate;
20    u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64,
21    NullString
22);
23
24macro_rules! impl_printf_arg_integer {
25    ( $( $t:ty, $signed:expr, $int_type:ty );* ) => {
26        $(
27            impl PrintfArgument for $t {
28                const IS_SIGNED: bool = $signed;
29
30                const IS_CHAR: bool      = is_compat::<$t, core::ffi::c_char>();
31                const IS_SHORT: bool     = is_compat::<$t, core::ffi::c_short>();
32                const IS_INT: bool       = is_compat::<$t, core::ffi::c_int>();
33                const IS_LONG: bool      = is_compat::<$t, core::ffi::c_long>();
34                const IS_LONG_LONG: bool = is_compat::<$t, core::ffi::c_longlong>();
35
36                #[cfg(any(feature = "libc", test, all(doc, feature = "doccfg")))]
37                const IS_SIZE: bool      = is_compat::<$t, libc::size_t>();
38
39                #[cfg(any(feature = "libc", test, all(doc, feature = "doccfg")))]
40                const IS_MAX: bool       = is_compat::<$t, libc::intmax_t>();
41
42                #[cfg(any(feature = "libc", test, all(doc, feature = "doccfg")))]
43                const IS_PTRDIFF: bool   = is_compat::<$t, libc::ptrdiff_t>();
44
45                type CPrintfType = LargerOf<Self, $int_type>;
46
47                #[inline]
48                fn as_c_val(self) -> Self::CPrintfType {
49                    self as LargerOf<Self, $int_type>
50                }
51            }
52        )*
53    };
54}
55
56impl_printf_arg_integer! {
57    u8,   false, c_uint;
58    i8,   true,  c_int;
59    u16,  false, c_uint;
60    i16,  true,  c_int;
61    u32,  false, c_uint;
62    i32,  true,  c_int;
63    u64,  false, c_uint;
64    i64,  true,  c_int;
65
66    // explicitly not implementing for {u128, i128} (no ABI guarantees)
67
68    usize, false, c_uint;
69    isize, true,  c_int
70}
71
72impl PrintfArgument for f32 {
73    const IS_FLOAT: bool = true;
74
75    type CPrintfType = c_double;
76
77    #[inline]
78    fn as_c_val(self) -> c_double {
79        self as c_double
80    }
81}
82
83impl PrintfArgument for f64 {
84    const IS_FLOAT: bool = true;
85
86    type CPrintfType = c_double;
87
88    #[inline]
89    fn as_c_val(self) -> c_double {
90        self as c_double
91    }
92}
93
94impl PrintfArgument for NullString {
95    type CPrintfType = *const c_char;
96
97    const IS_C_STRING: bool = true;
98
99    #[inline]
100    fn as_c_val(self) -> *const c_char {
101        self.as_ptr()
102    }
103}
104
105impl<T: AsRef<CStr> + ?Sized> PrintfArgumentPrivate for &T {}
106
107impl<T: AsRef<CStr> + ?Sized> PrintfArgument for &T {
108    type CPrintfType = *const c_char;
109
110    const IS_C_STRING: bool = true;
111
112    #[inline]
113    fn as_c_val(self) -> *const c_char {
114        let cs: &CStr = self.as_ref();
115        cs.as_ptr()
116    }
117}
118
119impl<T: Sized> PrintfArgumentPrivate for *const T {}
120
121impl<T: Sized> PrintfArgument for *const T {
122    type CPrintfType = *const c_void;
123
124    const IS_POINTER: bool = true;
125
126    #[inline]
127    fn as_c_val(self) -> *const c_void {
128        self as *const c_void
129    }
130}
131
132impl<T: Sized> PrintfArgumentPrivate for *mut T {}
133
134impl<T: Sized> PrintfArgument for *mut T {
135    type CPrintfType = *const c_void;
136
137    const IS_POINTER: bool = true;
138
139    #[inline]
140    fn as_c_val(self) -> *const c_void {
141        self as *mut c_void as *const c_void
142    }
143}