1#[macro_export]
3macro_rules! location {
4 () => {{
5 let location = format!(
6 "{}{}{}:{}",
7 $crate::color::auto($crate::function_name!()),
8 $crate::color::fore(" @ ", 220),
9 $crate::filename!(),
10 $crate::color::auto(line!().to_string())
11 );
12 location
13 }};
14 (begin) => {
15 $crate::tag!([
16 $crate::color::auto(format!("in function")),
17 $crate::location!()
18 ]
19 .join(" "))
20 };
21 (end) => {
22 $crate::tag!([
23 $crate::color::auto(format!("from function")),
24 $crate::location!()
25 ]
26 .join(" "))
27 };
28 (unexpected) => {
29 [
30 $crate::color::fore(format!("<unexpected branch in function"), 160),
31 $crate::location!(),
32 $crate::color::fore(format!(">"), 160),
33 ]
34 .join(" ")
35 };
36}
37#[macro_export]
39macro_rules! filename {
40 () => {{
41 let mut parts = file!()
42 .split(std::path::MAIN_SEPARATOR_STR)
43 .map(String::from)
44 .map(|part| $crate::color::auto(part.to_string()))
45 .collect::<Vec<String>>();
46 let (folder, filename) = if parts.len() > 1 {
47 let last = parts.remove(parts.len() - 1);
48 let parts = parts.iter().map(Clone::clone).collect::<Vec<String>>();
49 (parts, last)
50 } else {
51 (Vec::<String>::new(), parts[0].to_string())
52 };
53 if folder.len() > 1 {
54 format!(
55 "{}{}{}",
56 filename,
57 $crate::color::fore(" in ", 7),
58 folder.join(std::path::MAIN_SEPARATOR_STR)
59 )
60 } else {
61 filename
62 }
63 }};
64}
65#[macro_export]
67macro_rules! tag {
68 ($arg:expr) => {{
69 $crate::tag!($arg, 7)
70 }};
71 (close, $arg:expr) => {{
72 $crate::tag!(close, $arg, 7)
73 }};
74 ($arg:expr, $color:literal) => {{
75 format!(
76 "{}{}{}",
77 $crate::color::fore("<", $color),
78 $crate::color::auto($arg),
79 $crate::color::fore(">", $color),
80 )
81 }};
82 (close, $arg:expr, $color:literal) => {{
83 format!(
84 "{}{}{}",
85 $crate::color::fore("</", $color),
86 $arg,
87 $crate::color::fore(">", $color),
88 )
89 }};
90}
91
92#[macro_export]
94macro_rules! dbg {
95 ($arg:expr $(,)? ) => {{
96 eprintln!("{}", $crate::format_dbg_location!($arg));
97 $arg
98 }};
99 ($( $arg:expr ),* $(,)? ) => {{
100 eprintln!("{}", $crate::format_dbg_location!($($arg),*));
101 }};
102}
103
104#[macro_export]
105macro_rules! format_dbg {
106 ($arg:expr $(,)? ) => {{
107 $crate::indent!(
108 format!(
109 "{} = {}\n",
110 $crate::color::auto(stringify!(&$arg)),
111 $crate::color::auto(format!("{:#?}", &$arg))))
112
113 }};
114 ($( $arg:expr ),* $(,)? ) => {{
115 [$($crate::format_dbg!($arg)),*].join("\n")
116 }};
117}
118#[macro_export]
119macro_rules! format_dbg_location {
120 ($arg:expr $(,)? ) => {{
121 format!("{}", $crate::color::reset([$crate::location!(begin), $crate::format_dbg!($arg), $crate::location!(end)].join("\n")))
122 }};
123 ($( $arg:expr ),* $(,)? ) => {{
124 [$crate::location!(begin), $($crate::format_dbg!($arg)),*, $crate::location!(end)].join("\n")
125 }};
126}
127
128#[macro_export]
130macro_rules! indent {
131 ($indentation:literal, $obj:expr) => {{
132 format!("{}", $obj)
133 .lines()
134 .map(|line| format!("{}{}", " ".repeat($indentation), line))
135 .collect::<Vec<String>>()
136 .join("\n")
137 }};
138 ($obj:expr) => {{
139 $crate::indent!(4, $obj)
140 }};
141}
142#[macro_export]
144macro_rules! indent_objdump {
145 ($indentation:literal, $obj:expr) => {{
146 format!("{:#?}", $obj)
147 .lines()
148 .map(|line| format!("{}{}", " ".repeat($indentation), line))
149 .collect::<Vec<String>>()
150 .join("\n")
151 }};
152 ($obj:expr) => {{
153 $crate::indent_objdump!(4, $obj)
154 }};
155}
156
157#[macro_export]
159macro_rules! function_name {
160 () => {{
161 fn f() {}
162 fn type_name_of<T>(_: T) -> &'static str {
163 std::any::type_name::<T>()
164 }
165 let name = type_name_of(f);
166 let name = name
167 .strip_suffix("::f")
168 .unwrap()
169 .replace(format!("{}::", module_path!()).as_str(), "");
170 name
171 }};
172}
173
174#[macro_export]
176macro_rules! step {
177 ($text:expr $(,)?) => {{
178 $crate::step!(length=$crate::color::term_cols(), $text)
179 }};
180 (fg=$fg:expr, $text:expr $(,)?) => {{
181 $crate::step!(bg=$fg, fg=$crate::color::invert_bw($fg), length=$crate::color::term_cols(), $text)
182 }};
183 (bg=$bg:expr, fg=$fg:expr, $text:expr $(,)?) => {{
184 $crate::step!(bg=$bg, fg=$fg, length=$crate::color::term_cols(), $text)
185 }};
186 (length=$length:expr, $text:expr $(,)?) => {{
187 let (bg, fg) = $crate::color::couple(line!() as usize);
188 $crate::step!(bg=bg, fg=fg, length=$length, $text)
189 }};
190 (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $text:expr $(,)?) => {{
191 let text = $text.to_string();
192 let bar = $crate::color::ansi(
193 " ".repeat($length),
194 $fg as usize,
195 $bg as usize,
196 );
197 eprintln!(
198 "\n{}",
199 [
200 bar.clone(),
201 $crate::color::ansi(
202 $crate::color::pad_columns(
203 [
204 $crate::function_name!(),
205 [
206 file!().to_string(),
207 line!().to_string(),
208 ].join(":")
209 ].join(" ").to_string()
210 ),
211 $fg as usize,
212 $bg as usize,
213 ),
214 $crate::color::ansi(
215 $crate::color::pad_columns(
216 if text.is_empty() { String::new() } else { format!("{}", text) }
217 ),
218 $bg as usize,
219 $fg as usize,
220 ),
221 bar.clone(),
222 ].join("\n")
223 );
224 }};
225 (length=$length:expr, $text:expr, $( $arg:expr ),* $(,)? ) => {{
226 $crate::step!(length=$length, format_args!($text, $($arg,)*))
227 }};
228 () => {{
229 $crate::step!("")
230 }};
231}
232#[macro_export]
234macro_rules! step_dbg {
235 (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $($arg:expr),* $(,)?) => {{
236 let text = format!("{}", [
237 $($crate::indent!(format!("{} = {}", $crate::color::auto(stringify!($arg)), $crate::color::auto(format!("{:#?}", $arg))))),*
238 ].join("\n"));
239 $crate::step!(bg=$bg, fg=$fg, length=$length, text);
240 }};
241 (bg=$bg:expr, fg=$fg:expr, $($arg:expr),* $(,)?) => {{
242 $crate::step_dbg!(bg=$bg, fg=$fg, length=$crate::color::term_cols(), $($arg),*)
243 }};
244 (fg=$fg:expr, $($arg:expr),* $(,)?) => {{
245 $crate::step_dbg!(bg=$fg, fg=$crate::color::invert_bw($fg), length=$crate::color::term_cols(), $($arg),*)
246 }};
247 ($($arg:expr),* $(,)?) => {{
248 let fg=$crate::color::wrap(line!() as usize);
249 $crate::step_dbg!(bg=fg, fg=$crate::color::invert_bw(fg), length=$crate::color::term_cols(), $($arg),*)
250 }};
251 () => {{
252 $crate::step!("")
253 }};
254}
255
256#[macro_export]
258macro_rules! admonition {
259 ($color:literal, $message:expr) => {
260 $crate::admonition!($color, "{}", $message);
261 };
262 ($color:literal, $title:literal, $message:expr) => {
263 $crate::admonition!($color, title=$title, $message);
264 };
265
266 ($color:literal, title=$title:literal, $message:expr) => {
267 $crate::admonition!($color, title=$title, "{}", $message);
268 };
269 ($color:literal, title=$title:literal, $format:literal, $($arg:expr),* $(,)?) => {{
270 use crate::color;
271 eprintln!(
272 "\n{}",
273 [
274 color::ansi(
275 format!("{}:{} {}", crate::function_name!(), line!(), $title),
276 color::invert_bw($color).into(),
277 $color,
278 ),
279 color::ansi(
280 format!($format, $($arg),*),
281 $color,
282 color::invert_bw($color).into(),
283 )
284 ]
285 .join(" ")
286 );
287 }};
288 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {{
289 use crate::color;
290 eprintln!(
291 "\n{}",
292 [
293 color::ansi(
294 format!("{}:{}", crate::function_name!(), line!()),
295 color::invert_bw($color).into(),
296 $color,
297 ),
298 color::ansi(
299 format!($format, $($arg),*),
300 $color,
301 color::invert_bw($color).into(),
302 )
303 ]
304 .join(" ")
305 );
306 }};
307}
308
309#[macro_export]
311macro_rules! warn {
312 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
313 $crate::admonition!($color, title="WARNING", $format, $($arg),*);
314 };
315 ($color:literal, $message:expr) => {
316 $crate::admonition!($color, title="WARNING", $message);
317 };
318 ($message:expr) => {
319 $crate::warn!(220, $message);
320 };
321}
322
323#[macro_export]
325macro_rules! info {
326 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
327 $crate::admonition!($color, title="INFO", $format, $($arg),*);
328 };
329 ($color:literal, $message:expr) => {
330 $crate::admonition!($color, title="INFO", $message);
331 };
332 ($message:expr) => {
333 $crate::info!(74, $message);
334 };
335}
336
337#[macro_export]
339macro_rules! format_byte {
340 (hex_only, $byte:expr $(,)? ) => {{
341 use $crate::color::{auto, fore, from_byte, pad};
342 let color = $crate::color::from_byte($byte);
343 $crate::color::fore(format!("0x{:02x}", $byte), color.into())
344 }};
345 (hex, $byte:expr $(,)? ) => {{
346 use $crate::color::{auto, fore, from_bytes, pad};
347 let color = $crate::color::from_bytes(&[$byte]);
348 [
349 $crate::color::fore(format!("0x{:02x}", $byte), color.into()),
350 if $byte < 127 {
351 $crate::color::fore(
352 format!("{:#?}", char::from($byte).to_string()),
353 color.into(),
354 )
355 } else {
356 String::new()
357 },
358 ]
359 .iter()
360 .filter(|c| !c.is_empty())
361 .map(String::from)
362 .collect::<Vec<String>>()
363 .join(" => ")
364 }};
365 (bin, $byte:expr $(,)? ) => {{
366 use $crate::color::{auto, fore, from_bytes, pad};
367 let color = $crate::color::from_bytes(&[$byte]);
368 [
369 $crate::color::fore(format!("0b{:08b}", $byte), color.into()),
370 if $byte < 127 {
371 $crate::color::fore(
372 format!("{:#?}", char::from($byte).to_string()),
373 color.into(),
374 )
375 } else {
376 String::new()
377 },
378 ]
379 .iter()
380 .filter(|c| !c.is_empty())
381 .map(String::from)
382 .collect::<Vec<String>>()
383 .join(" => ")
384 }};
385 ($byte:expr $(,)? ) => {{
386 use $crate::color::{auto, fore, from_bytes, pad};
387 let color = $crate::color::from_bytes(&[$byte]);
388 [
389 $crate::color::fore(format!("0x{:02x}", $byte), color.into()),
390 $crate::color::fore(format!("0b{:08b}", $byte), color.into()),
391 $crate::color::fore(format!("{:#?}", $byte), color.into()),
392 if $byte < 127 {
393 $crate::color::fore(
394 format!("{:#?}", char::from($byte).to_string()),
395 color.into(),
396 )
397 } else {
398 String::new()
399 },
400 ]
401 .iter()
402 .filter(|c| !c.is_empty())
403 .map(String::from)
404 .collect::<Vec<String>>()
405 .join(" => ")
406 }};
407}
408#[macro_export]
410macro_rules! dbg_byte {
411 ($byte:expr $(,)? ) => {{
412 use $crate::color::{auto, fore, from_display};
413 let color = $crate::color::from_display($byte);
414 $crate::step!(format!(
415 "{} = {}",
416 $crate::color::auto(stringify!($byte)),
417 $crate::format_byte!($byte)
418 ));
419 $byte
420 }};
421}
422
423#[macro_export]
425macro_rules! dbg_bytes {
426 ($slice:expr $(,)? ) => {{
427 use $crate::color::{auto, back, fore, from_display, pad};
428 $crate::step!($crate::indent!(format!(
429 "{} = {}",
430 $crate::color::auto(stringify!($slice)),
431 $crate::format_bytes!($slice)
432 )));
433 $slice
434 }};
435}
436#[macro_export]
438macro_rules! dbg_bytes_str {
439 ($slice:expr $(,)? ) => {{
440 use $crate::color::{auto, back, fore, from_display, pad};
441 use $crate::indent;
442 eprintln!(
443 "\n{}",
444 [
445 $crate::location!(begin),
446 String::new(),
447 $crate::color::auto(stringify!($slice)),
448 $crate::format_bytes_str!($slice),
449 String::new(),
450 $crate::location!(end),
451 ]
452 .join("\n")
453 );
454 $slice
455 }};
456}
457#[macro_export]
459macro_rules! dbg_bytes_if_str {
460 ($slice:expr $(,)? ) => {
461 if let Ok(c) = std::str::from_utf8($slice) {
462 $crate::dbg_bytes!($slice)
463 } else {
464 $slice
465 }
466 };
467}
468#[macro_export]
470macro_rules! format_bytes {
471 ($slice:expr $(,)? ) => {
472 $crate::format_bytes!($slice, " => ");
473 };
474 (hex, $slice:expr $(,)? ) => {
475 $crate::format_bytes!(hex, $slice, " => ");
476 };
477 (bin, $slice:expr $(,)? ) => {
478 $crate::format_bytes!(bin, $slice, " => ");
479 };
480 ($slice:expr, $sep:literal $(,)? ) => {{
481 [
482 format!(
483 "[\n{}]",
484 $slice
485 .iter()
486 .map(Clone::clone)
487 .map(|byte| format!(
488 "{}, // {}\n",
489 $crate::indent!($crate::format_byte!(byte)),
490 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
491 ))
492 .collect::<Vec<String>>()
493 .join("")
494 ),
495 format!("{} bytes", $slice.len()),
496 std::str::from_utf8($slice)
497 .map(|s| {
498 let chars = s.chars().collect::<Vec<char>>();
499 format!(
500 "\"{s}\" => {} chars => [{}]",
501 chars.len(),
502 chars
503 .iter()
504 .map(|c| format!("{c:?}"))
505 .collect::<Vec<String>>()
506 .join(", ")
507 )
508 })
509 .unwrap_or_default(),
510 ]
511 .iter()
512 .filter(|c| !c.is_empty())
513 .map(String::from)
514 .collect::<Vec<String>>()
515 .join($sep.to_string().as_str())
516 }};
517 (hex, $slice:expr, $sep:literal $(,)? ) => {{
518 [
519 format!(
520 "[\n{}]",
521 $slice
522 .iter()
523 .map(Clone::clone)
524 .map(|byte| format!(
525 "{}, // {}\n",
526 $crate::indent!($crate::format_byte!(hex, byte)),
527 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
528 ))
529 .collect::<Vec<String>>()
530 .join("")
531 ),
532 std::str::from_utf8($slice)
533 .map(|s| format!("{s:#?}"))
534 .unwrap_or_default(),
535 ]
536 .iter()
537 .filter(|c| !c.is_empty())
538 .map(String::from)
539 .collect::<Vec<String>>()
540 .join($sep.to_string().as_str())
541 }};
542 (bin, $slice:expr, $sep:literal $(,)? ) => {{
543 [
544 format!(
545 "[\n{}]",
546 $slice
547 .iter()
548 .map(Clone::clone)
549 .map(|byte| format!(
550 "{}, // {}\n",
551 $crate::indent!($crate::format_byte!(bin, byte)),
552 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
553 ))
554 .collect::<Vec<String>>()
555 .join("")
556 ),
557 std::str::from_utf8($slice)
558 .map(|s| format!("{s:#?}"))
559 .unwrap_or_default(),
560 ]
561 .iter()
562 .filter(|c| !c.is_empty())
563 .map(String::from)
564 .collect::<Vec<String>>()
565 .join($sep.to_string().as_str())
566 }};
567}
568
569#[macro_export]
571macro_rules! format_bytes_str {
572 ($slice:expr $(,)? ) => {
573 $crate::format_bytes_str!($slice, " => ");
574 };
575 ($slice:expr, $sep:literal $(,)? ) => {{
576 [
577 format!(
578 "[{}]",
579 $slice
580 .iter()
581 .map(Clone::clone)
582 .map(|byte| $crate::format_byte!(hex_only, byte))
583 .collect::<Vec<String>>()
584 .join(", ")
585 ),
586 std::str::from_utf8($slice)
587 .map(|s| format!("{s:#?}"))
588 .unwrap_or_default(),
589 ]
590 .iter()
591 .filter(|c| !c.is_empty())
592 .map(String::from)
593 .collect::<Vec<String>>()
594 .join($sep.to_string().as_str())
595 }};
596}