1mod integers;
2mod traits;
3
4use core::fmt::Write as _;
5
6use crate::{Format, Formatter, Str};
7
8pub use self::integers::*;
9pub use bitflags::bitflags;
10
11pub trait UnsignedInt {}
12impl UnsignedInt for u8 {}
13impl UnsignedInt for u16 {}
14impl UnsignedInt for u32 {}
15impl UnsignedInt for u64 {}
16impl UnsignedInt for u128 {}
17
18#[cfg(feature = "unstable-test")]
19thread_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")]
26pub 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")]
32pub 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")]
38pub 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")]
45pub 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)]
51pub 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")]
61pub 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)]
67pub unsafe fn release() {
68 unsafeextern "Rust" {
69 unsafefn _defmt_release();
70 }
71 _defmt_release()
72}
73
74#[cfg(feature = "unstable-test")]
75pub fn write(bytes: &[u8]) {
76 BYTES.with(|b| b.borrow_mut().extend(bytes))
77}
78
79#[cfg(not(feature = "unstable-test"))]
80#[inline(always)]
81pub 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")]
90pub fn timestamp(_fmt: crate::Formatter<'_>) {}
91
92#[cfg(not(feature = "unstable-test"))]
93#[inline(always)]
94pub 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`.
102pub fn make_istr(address: u16) -> Str {
103 Str { address }
104}
105
106/// Create a Formatter.
107pub fn make_formatter<'a>() -> Formatter<'a> {
108 Formatter {
109 _phantom: core::marker::PhantomData,
110 }
111}
112
113pub fn truncate<T>(x: impl traits::Truncate<T>) -> T {
114 x.truncate()
115}
116
117pub 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")]
123pub fn panic() -> ! {
124 panic!()
125}
126
127#[cfg(not(feature = "unstable-test"))]
128#[inline(always)]
129pub fn panic() -> ! {
130 unsafeextern "Rust" {
131 unsafefn _defmt_panic() -> !;
132 }
133 unsafe { _defmt_panic() }
134}
135
136/// Implementation detail
137pub fn fmt<T: Format + ?Sized>(f: &T) {
138 istr(&T::_format_tag());
139 f._format_data();
140}
141
142/// Implementation detail
143pub 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
152pub fn f32(b: &f32) {
153 write(&f32::to_bits(*b).to_le_bytes())
154}
155
156/// Implementation detail
157pub fn f64(b: &f64) {
158 write(&f64::to_bits(*b).to_le_bytes())
159}
160
161/// Implementation detail
162pub fn char(b: &char) {
163 write(&(*b as u32).to_le_bytes())
164}
165
166pub fn str(s: &str) {
167 usize(&s.len());
168 write(s.as_bytes());
169}
170
171pub 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.
177pub 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.
182pub 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
190pub fn istr(s: &Str) {
191 write(&s.address.to_le_bytes())
192}
193
194/// Implementation detail
195pub fn bool(b: &bool) {
196 u8(&(*b as u8));
197}
198
199/// Implementation detail
200pub fn debug(val: &dyn core::fmt::Debug) {
201 core::write!(FmtWrite, "{val:?}").ok();
202 write(&[0xff]);
203}
204
205/// Implementation detail
206pub fn display(val: &dyn core::fmt::Display) {
207 core::write!(FmtWrite, "{val}").ok();
208 write(&[0xff]);
209}
210
211#[inline(never)]
212pub unsafe fn acquire_and_header(s: &Str) {
213 acquire();
214 istr(s);
215 timestamp(fmt:make_formatter());
216}
217
218#[inline(never)]
219pub 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
228struct FmtWrite;
229
230impl 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