1use core::{fmt, sync::atomic::AtomicBool};
2
3pub mod console;
4mod uart;
5
6static PRINT_ERR: AtomicBool = AtomicBool::new(false);
7
8macro_rules! impl_copy_clone_deref_wrapper {
9 ($new_type:tt <$generic:tt>) => {
10 impl<$generic> ::core::clone::Clone for $new_type<$generic>
11 where
12 $generic: ::core::clone::Clone,
13 {
14 fn clone(&self) -> Self {
15 $new_type(self.0.clone())
16 }
17 }
18
19 impl<$generic> ::core::marker::Copy for $new_type<$generic> where
20 $generic: ::core::marker::Copy
21 {
22 }
23
24 impl<$generic> ::core::ops::Deref for $new_type<$generic> {
25 type Target = $generic;
26
27 fn deref(&self) -> &Self::Target {
28 &self.0
29 }
30 }
31
32 impl<$generic> ::core::ops::DerefMut for $new_type<$generic> {
33 fn deref_mut(&mut self) -> &mut Self::Target {
34 &mut self.0
35 }
36 }
37 };
38}
39
40#[repr(transparent)]
43pub struct NoDebug<T>(pub T);
44
45impl<T> fmt::Debug for NoDebug<T> {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(f, "[no_debug]")
48 }
49}
50
51impl_copy_clone_deref_wrapper!(NoDebug<T>);
52
53#[repr(transparent)]
55pub struct HexArray<T>(pub T);
56
57trait ArrayTrait {
59 type Item;
60 fn data(&self) -> &[Self::Item];
61}
62
63impl<T> ArrayTrait for T
64where
65 T: AsRef<[u8]>,
66{
67 type Item = u8;
68 fn data(&self) -> &[Self::Item] {
69 self.as_ref()
70 }
71}
72
73impl<T, U> fmt::Debug for HexArray<T>
74where
75 T: ArrayTrait<Item = U>,
76 U: fmt::UpperHex,
77{
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 write!(f, "[")?;
81 for (index, data) in self.0.data().iter().enumerate() {
82 if index > 0 {
83 write!(f, ", ")?;
84 }
85 write!(f, "{data:#04X}")?;
88 }
89 write!(f, "]")
90 }
91}
92
93impl_copy_clone_deref_wrapper!(HexArray<T>);
94
95#[repr(transparent)]
97pub struct ByteStr<T>(pub T);
98
99impl<T> fmt::Debug for ByteStr<T>
100where
101 T: AsRef<[u8]>,
102{
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(f, "b\"")?;
105 for &c in self.0.as_ref().iter() {
107 if c.is_ascii_graphic() || c == b' ' {
108 write!(f, "{}", c as char)?;
109 } else {
110 write!(f, "\\x{c:02X}")?;
111 }
112 }
113 write!(f, "\"")
114 }
115}
116
117impl_copy_clone_deref_wrapper!(ByteStr<T>);
118
119#[allow(dead_code)]
120pub fn hexdump(buf: &[u8]) {
121 console::run_with_console(|inner| {
124 for i in 0..buf.len() / 16 {
126 write!(inner, "{:08X}: ", i * 16)?;
127 for j in 0..16 {
128 write!(inner, "{:02X} ", buf[i * 16 + j])?;
129 }
130 write!(inner, " ")?;
132 for j in 0..16 {
133 let c = buf[i * 16 + j];
134 if (32..127).contains(&c) {
135 write!(inner, "{}", c as char)?;
136 } else {
137 write!(inner, ".")?;
138 }
139 }
140 writeln!(inner)?;
141 }
142 let remaining = buf.len() % 16;
144 if remaining != 0 {
145 let remaining_start = (buf.len() / 16) * 16;
146
147 write!(inner, "{remaining_start:08X}: ")?;
148 for c in buf[remaining_start..].iter() {
149 write!(inner, "{c:02X} ")?;
150 }
151 for _ in 0..(16 - remaining) {
152 write!(inner, " ")?;
153 }
154 write!(inner, " ")?;
156 for &c in buf[remaining_start..].iter() {
157 if (32..127).contains(&c) {
158 write!(inner, "{}", c as char)?;
159 } else {
160 write!(inner, ".")?;
161 }
162 }
163 writeln!(inner)?;
164 }
165 Ok::<(), fmt::Error>(())
166 })
167 .unwrap();
168}
169
170pub fn _print(args: ::core::fmt::Arguments) {
171 console::run_with_console(|inner| inner.write_fmt(args)).unwrap();
172}
173
174#[allow(dead_code)]
177pub fn set_err_enable(enable: bool) {
178 PRINT_ERR.store(enable, core::sync::atomic::Ordering::Release);
179}
180
181pub fn _eprint(args: ::core::fmt::Arguments) {
182 if PRINT_ERR.load(core::sync::atomic::Ordering::Acquire) {
183 _print(args);
184 }
185}