Skip to main content

kprint/
backend.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5unsafe extern "C" {
6    pub fn printf(format: *const core::ffi::c_char, ...) -> core::ffi::c_int;
7
8    pub fn snprintf(
9        str: *mut core::ffi::c_char,
10        size: usize,
11        format: *const core::ffi::c_char,
12        ...
13    ) -> core::ffi::c_int;
14}
15
16/// Trait implemented by types that can be formatted as a string slice (`%.*s`).
17pub trait AsKPrintStr {
18    fn kprint_len(&self) -> core::ffi::c_int;
19    fn kprint_ptr(&self) -> *const core::ffi::c_char;
20}
21
22impl AsKPrintStr for &str {
23    #[inline(always)]
24    fn kprint_len(&self) -> core::ffi::c_int {
25        self.len() as core::ffi::c_int
26    }
27    #[inline(always)]
28    fn kprint_ptr(&self) -> *const core::ffi::c_char {
29        self.as_ptr() as *const core::ffi::c_char
30    }
31}
32
33impl AsKPrintStr for str {
34    #[inline(always)]
35    fn kprint_len(&self) -> core::ffi::c_int {
36        self.len() as core::ffi::c_int
37    }
38    #[inline(always)]
39    fn kprint_ptr(&self) -> *const core::ffi::c_char {
40        self.as_ptr() as *const core::ffi::c_char
41    }
42}
43
44impl AsKPrintStr for &[u8] {
45    #[inline(always)]
46    fn kprint_len(&self) -> core::ffi::c_int {
47        self.len() as core::ffi::c_int
48    }
49    #[inline(always)]
50    fn kprint_ptr(&self) -> *const core::ffi::c_char {
51        self.as_ptr() as *const core::ffi::c_char
52    }
53}
54
55impl AsKPrintStr for [u8] {
56    #[inline(always)]
57    fn kprint_len(&self) -> core::ffi::c_int {
58        self.len() as core::ffi::c_int
59    }
60    #[inline(always)]
61    fn kprint_ptr(&self) -> *const core::ffi::c_char {
62        self.as_ptr() as *const core::ffi::c_char
63    }
64}
65
66impl<const N: usize> AsKPrintStr for [u8; N] {
67    #[inline(always)]
68    fn kprint_len(&self) -> core::ffi::c_int {
69        self.len() as core::ffi::c_int
70    }
71    #[inline(always)]
72    fn kprint_ptr(&self) -> *const core::ffi::c_char {
73        self.as_ptr() as *const core::ffi::c_char
74    }
75}
76
77impl<const N: usize> AsKPrintStr for &[u8; N] {
78    #[inline(always)]
79    fn kprint_len(&self) -> core::ffi::c_int {
80        self.len() as core::ffi::c_int
81    }
82    #[inline(always)]
83    fn kprint_ptr(&self) -> *const core::ffi::c_char {
84        self.as_ptr() as *const core::ffi::c_char
85    }
86}
87
88impl AsKPrintStr for &core::ffi::CStr {
89    #[inline(always)]
90    fn kprint_len(&self) -> core::ffi::c_int {
91        self.to_bytes().len() as core::ffi::c_int
92    }
93    #[inline(always)]
94    fn kprint_ptr(&self) -> *const core::ffi::c_char {
95        self.as_ptr()
96    }
97}
98
99impl AsKPrintStr for core::ffi::CStr {
100    #[inline(always)]
101    fn kprint_len(&self) -> core::ffi::c_int {
102        self.to_bytes().len() as core::ffi::c_int
103    }
104    #[inline(always)]
105    fn kprint_ptr(&self) -> *const core::ffi::c_char {
106        self.as_ptr()
107    }
108}
109
110/// Trait implemented by types that can be formatted as a null-terminated C string (`%s`).
111pub trait AsKPrintCString {
112    fn as_c_ptr(&self) -> *const core::ffi::c_char;
113}
114
115impl AsKPrintCString for *const i8 {
116    #[inline(always)]
117    fn as_c_ptr(&self) -> *const core::ffi::c_char {
118        *self as *const core::ffi::c_char
119    }
120}
121
122impl AsKPrintCString for *mut i8 {
123    #[inline(always)]
124    fn as_c_ptr(&self) -> *const core::ffi::c_char {
125        *self as *const core::ffi::c_char
126    }
127}
128
129impl AsKPrintCString for *const u8 {
130    #[inline(always)]
131    fn as_c_ptr(&self) -> *const core::ffi::c_char {
132        *self as *const core::ffi::c_char
133    }
134}
135
136impl AsKPrintCString for *mut u8 {
137    #[inline(always)]
138    fn as_c_ptr(&self) -> *const core::ffi::c_char {
139        *self as *const core::ffi::c_char
140    }
141}
142
143impl AsKPrintCString for &core::ffi::CStr {
144    #[inline(always)]
145    fn as_c_ptr(&self) -> *const core::ffi::c_char {
146        self.as_ptr()
147    }
148}
149
150impl AsKPrintCString for core::ffi::CStr {
151    #[inline(always)]
152    fn as_c_ptr(&self) -> *const core::ffi::c_char {
153        self.as_ptr()
154    }
155}
156
157/// Trait implemented by signed integer types formatted with `%lld`.
158pub trait AsKPrintSignedInt {
159    fn as_c_longlong(&self) -> core::ffi::c_longlong;
160}
161
162macro_rules! impl_signed_int {
163    ($($t:ty),*) => {
164        $(
165            impl AsKPrintSignedInt for $t {
166                #[inline(always)]
167                fn as_c_longlong(&self) -> core::ffi::c_longlong {
168                    *self as core::ffi::c_longlong
169                }
170            }
171            impl AsKPrintSignedInt for &$t {
172                #[inline(always)]
173                fn as_c_longlong(&self) -> core::ffi::c_longlong {
174                    **self as core::ffi::c_longlong
175                }
176            }
177        )*
178    };
179}
180
181impl_signed_int!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, bool, char);
182
183/// Trait implemented by unsigned integer types formatted with `%llu`, `%llx`, `%llo`.
184pub trait AsKPrintUnsignedInt {
185    fn as_c_ulonglong(&self) -> core::ffi::c_ulonglong;
186}
187
188macro_rules! impl_unsigned_int {
189    ($($t:ty),*) => {
190        $(
191            impl AsKPrintUnsignedInt for $t {
192                #[inline(always)]
193                fn as_c_ulonglong(&self) -> core::ffi::c_ulonglong {
194                    *self as core::ffi::c_ulonglong
195                }
196            }
197            impl AsKPrintUnsignedInt for &$t {
198                #[inline(always)]
199                fn as_c_ulonglong(&self) -> core::ffi::c_ulonglong {
200                    **self as core::ffi::c_ulonglong
201                }
202            }
203        )*
204    };
205}
206
207impl_unsigned_int!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, bool);
208
209/// Trait implemented by pointer types formatted with `%p`.
210pub trait AsKPrintPointer {
211    fn as_c_ptr_void(&self) -> *const core::ffi::c_void;
212}
213
214impl<T: ?Sized> AsKPrintPointer for *const T {
215    #[inline(always)]
216    fn as_c_ptr_void(&self) -> *const core::ffi::c_void {
217        *self as *const core::ffi::c_void
218    }
219}
220
221impl<T: ?Sized> AsKPrintPointer for *mut T {
222    #[inline(always)]
223    fn as_c_ptr_void(&self) -> *const core::ffi::c_void {
224        *self as *const core::ffi::c_void
225    }
226}
227
228impl<T: ?Sized> AsKPrintPointer for &T {
229    #[inline(always)]
230    fn as_c_ptr_void(&self) -> *const core::ffi::c_void {
231        *self as *const T as *const core::ffi::c_void
232    }
233}
234
235impl<T: ?Sized> AsKPrintPointer for &mut T {
236    #[inline(always)]
237    fn as_c_ptr_void(&self) -> *const core::ffi::c_void {
238        *self as *const T as *const core::ffi::c_void
239    }
240}
241
242impl AsKPrintPointer for usize {
243    #[inline(always)]
244    fn as_c_ptr_void(&self) -> *const core::ffi::c_void {
245        *self as *const core::ffi::c_void
246    }
247}
248
249/// Trait implemented by types that can be formatted as a character (`{:c}`).
250pub trait AsKPrintChar {
251    fn kprint_encode_char(&self, buf: &mut [u8; 4])
252    -> (core::ffi::c_int, *const core::ffi::c_char);
253}
254
255impl AsKPrintChar for char {
256    #[inline(always)]
257    fn kprint_encode_char(
258        &self,
259        buf: &mut [u8; 4],
260    ) -> (core::ffi::c_int, *const core::ffi::c_char) {
261        let s = self.encode_utf8(buf);
262        (s.len() as core::ffi::c_int, s.as_ptr() as *const core::ffi::c_char)
263    }
264}
265
266impl AsKPrintChar for &char {
267    #[inline(always)]
268    fn kprint_encode_char(
269        &self,
270        buf: &mut [u8; 4],
271    ) -> (core::ffi::c_int, *const core::ffi::c_char) {
272        (*self).kprint_encode_char(buf)
273    }
274}
275
276impl AsKPrintChar for u8 {
277    #[inline(always)]
278    fn kprint_encode_char(
279        &self,
280        buf: &mut [u8; 4],
281    ) -> (core::ffi::c_int, *const core::ffi::c_char) {
282        buf[0] = *self;
283        (1, buf.as_ptr() as *const core::ffi::c_char)
284    }
285}
286
287impl AsKPrintChar for &u8 {
288    #[inline(always)]
289    fn kprint_encode_char(
290        &self,
291        buf: &mut [u8; 4],
292    ) -> (core::ffi::c_int, *const core::ffi::c_char) {
293        (*self).kprint_encode_char(buf)
294    }
295}