1 | mod integers; |
2 | mod traits; |
3 | |
4 | use core::fmt::Write as _; |
5 | |
6 | use crate::{Format, Formatter, Str}; |
7 | |
8 | pub use self::integers::*; |
9 | pub use bitflags::bitflags; |
10 | |
11 | pub trait UnsignedInt {} |
12 | impl UnsignedInt for u8 {} |
13 | impl UnsignedInt for u16 {} |
14 | impl UnsignedInt for u32 {} |
15 | impl UnsignedInt for u64 {} |
16 | impl UnsignedInt for u128 {} |
17 | |
18 | #[cfg (feature = "unstable-test" )] |
19 | thread_local! { |
20 | static I: core::sync::atomic::AtomicU16 = const { core::sync::atomic::AtomicU16::new(0) }; |
21 | static BYTES: core::cell::RefCell<Vec<u8>> = const { core::cell::RefCell::new(Vec::new()) }; |
22 | } |
23 | |
24 | /// For testing purposes |
25 | #[cfg (feature = "unstable-test" )] |
26 | pub fn fetch_string_index() -> u16 { |
27 | I.with(|i| i.load(core::sync::atomic::Ordering::Relaxed)) |
28 | } |
29 | |
30 | /// For testing purposes |
31 | #[cfg (feature = "unstable-test" )] |
32 | pub fn fetch_add_string_index() -> u16 { |
33 | I.with(|i| i.fetch_add(1, core::sync::atomic::Ordering::Relaxed)) |
34 | } |
35 | |
36 | /// Get and clear the logged bytes |
37 | #[cfg (feature = "unstable-test" )] |
38 | pub fn fetch_bytes() -> Vec<u8> { |
39 | BYTES.with(|b| core::mem::take(&mut *b.borrow_mut())) |
40 | } |
41 | |
42 | /// Only to be used by the defmt macros |
43 | /// Safety: must be paired with a later call to release() |
44 | #[cfg (feature = "unstable-test" )] |
45 | pub unsafe fn acquire() {} |
46 | |
47 | /// Only to be used by the defmt macros |
48 | /// Safety: must be paired with a later call to release() |
49 | #[cfg (not(feature = "unstable-test" ))] |
50 | #[inline (always)] |
51 | pub unsafe fn acquire() { |
52 | unsafeextern "Rust" { |
53 | unsafefn _defmt_acquire(); |
54 | } |
55 | _defmt_acquire() |
56 | } |
57 | |
58 | /// Only to be used by the defmt macros |
59 | /// Safety: must follow an earlier call to acquire() |
60 | #[cfg (feature = "unstable-test" )] |
61 | pub unsafe fn release() {} |
62 | |
63 | /// Only to be used by the defmt macros |
64 | /// Safety: must follow an earlier call to acquire() |
65 | #[cfg (not(feature = "unstable-test" ))] |
66 | #[inline (always)] |
67 | pub unsafe fn release() { |
68 | unsafeextern "Rust" { |
69 | unsafefn _defmt_release(); |
70 | } |
71 | _defmt_release() |
72 | } |
73 | |
74 | #[cfg (feature = "unstable-test" )] |
75 | pub fn write(bytes: &[u8]) { |
76 | BYTES.with(|b| b.borrow_mut().extend(bytes)) |
77 | } |
78 | |
79 | #[cfg (not(feature = "unstable-test" ))] |
80 | #[inline (always)] |
81 | pub fn write(bytes: &[u8]) { |
82 | unsafeextern "Rust" { |
83 | unsafefn _defmt_write(bytes: &[u8]); |
84 | } |
85 | unsafe { _defmt_write(bytes) } |
86 | } |
87 | |
88 | /// For testing purposes |
89 | #[cfg (feature = "unstable-test" )] |
90 | pub fn timestamp(_fmt: crate::Formatter<'_>) {} |
91 | |
92 | #[cfg (not(feature = "unstable-test" ))] |
93 | #[inline (always)] |
94 | pub fn timestamp(fmt: crate::Formatter<'_>) { |
95 | unsafeextern "Rust" { |
96 | unsafefn _defmt_timestamp(_: crate::Formatter<'_>); |
97 | } |
98 | unsafe { _defmt_timestamp(fmt) } |
99 | } |
100 | |
101 | /// Returns the interned string at `address`. |
102 | pub fn make_istr(address: u16) -> Str { |
103 | Str { address } |
104 | } |
105 | |
106 | /// Create a Formatter. |
107 | pub fn make_formatter<'a>() -> Formatter<'a> { |
108 | Formatter { |
109 | _phantom: core::marker::PhantomData, |
110 | } |
111 | } |
112 | |
113 | pub fn truncate<T>(x: impl traits::Truncate<T>) -> T { |
114 | x.truncate() |
115 | } |
116 | |
117 | pub fn into_result<T: traits::IntoResult>(x: T) -> Result<T::Ok, T::Error> { |
118 | x.into_result() |
119 | } |
120 | |
121 | /// For testing purposes |
122 | #[cfg (feature = "unstable-test" )] |
123 | pub fn panic() -> ! { |
124 | panic!() |
125 | } |
126 | |
127 | #[cfg (not(feature = "unstable-test" ))] |
128 | #[inline (always)] |
129 | pub fn panic() -> ! { |
130 | unsafeextern "Rust" { |
131 | unsafefn _defmt_panic() -> !; |
132 | } |
133 | unsafe { _defmt_panic() } |
134 | } |
135 | |
136 | /// Implementation detail |
137 | pub fn fmt<T: Format + ?Sized>(f: &T) { |
138 | istr(&T::_format_tag()); |
139 | f._format_data(); |
140 | } |
141 | |
142 | /// Implementation detail |
143 | pub fn fmt_slice<T: Format>(values: &[T]) { |
144 | usize(&values.len()); |
145 | istr(&T::_format_tag()); |
146 | for value: &T in values { |
147 | value._format_data(); |
148 | } |
149 | } |
150 | |
151 | /// Implementation detail |
152 | pub fn f32(b: &f32) { |
153 | write(&f32::to_bits(*b).to_le_bytes()) |
154 | } |
155 | |
156 | /// Implementation detail |
157 | pub fn f64(b: &f64) { |
158 | write(&f64::to_bits(*b).to_le_bytes()) |
159 | } |
160 | |
161 | /// Implementation detail |
162 | pub fn char(b: &char) { |
163 | write(&(*b as u32).to_le_bytes()) |
164 | } |
165 | |
166 | pub fn str(s: &str) { |
167 | usize(&s.len()); |
168 | write(s.as_bytes()); |
169 | } |
170 | |
171 | pub fn slice(s: &[u8]) { |
172 | usize(&s.len()); |
173 | write(bytes:s); |
174 | } |
175 | |
176 | // NOTE: This is passed `&[u8; N]` – it's just coerced to a slice. |
177 | pub fn u8_array(a: &[u8]) { |
178 | write(bytes:a); |
179 | } |
180 | |
181 | // NOTE: This is passed `&[u8; N]` – it's just coerced to a slice. |
182 | pub fn fmt_array<T: Format>(a: &[T]) { |
183 | istr(&T::_format_tag()); |
184 | for value: &T in a { |
185 | value._format_data(); |
186 | } |
187 | } |
188 | |
189 | /// Implementation detail |
190 | pub fn istr(s: &Str) { |
191 | write(&s.address.to_le_bytes()) |
192 | } |
193 | |
194 | /// Implementation detail |
195 | pub fn bool(b: &bool) { |
196 | u8(&(*b as u8)); |
197 | } |
198 | |
199 | /// Implementation detail |
200 | pub fn debug(val: &dyn core::fmt::Debug) { |
201 | core::write!(FmtWrite, " {val:?}" ).ok(); |
202 | write(&[0xff]); |
203 | } |
204 | |
205 | /// Implementation detail |
206 | pub fn display(val: &dyn core::fmt::Display) { |
207 | core::write!(FmtWrite, " {val}" ).ok(); |
208 | write(&[0xff]); |
209 | } |
210 | |
211 | #[inline (never)] |
212 | pub unsafe fn acquire_and_header(s: &Str) { |
213 | acquire(); |
214 | istr(s); |
215 | timestamp(fmt:make_formatter()); |
216 | } |
217 | |
218 | #[inline (never)] |
219 | pub fn acquire_header_and_release(s: &Str) { |
220 | // safety: will be released a few lines further down |
221 | unsafe { acquire() }; |
222 | istr(s); |
223 | timestamp(fmt:make_formatter()); |
224 | // safety: acquire() was called a few lines above |
225 | unsafe { release() }; |
226 | } |
227 | |
228 | struct FmtWrite; |
229 | |
230 | impl core::fmt::Write for FmtWrite { |
231 | fn write_str(&mut self, s: &str) -> core::fmt::Result { |
232 | write(s.as_bytes()); |
233 | Ok(()) |
234 | } |
235 | } |
236 | |