1#[macro_export]
3macro_rules! location {
4 () => {{
5 let location = format!(
6 "{}{}{}:{}",
7 $crate::color::auto($crate::function_name!()),
8 $crate::color::ansi(" @ ", 220, 16),
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
69 (@open, $arg:expr) => {{
70 $crate::tag!(@open, $arg, 7, @color=fore)
71 }};
72 (@open, $arg:expr, @color=auto) => {{
73 $crate::tag!(@open, $arg, 7, @color=auto)
74 }};
75 (@open, $arg:expr, @color=fore) => {{
76 $crate::tag!(@open, $arg, 7, @color=fore)
77 }};
78 (@open, $arg:expr, @color=$color:expr) => {{
79 $crate::tag!(@open, $arg, 7, @color=$color)
80 }};
81
82 (@open, $arg:expr, $color:expr) => {{
83 $crate::tag!(@open, $arg, $color, @color=$color)
84 }};
85 (@open, $arg:expr, $color:expr, @color=auto) => {{
86 let auto_color = $crate::color::from_display($arg) as usize;
87 format!(
88 "{}{}{}",
89 $crate::color::fore("<", $color),
90 $crate::color::fore($arg, auto_color),
91 $crate::color::fore(">", $color),
92 )
93 }};
94 (@open, $arg:expr, $color:expr, @color=fore) => {{
95 format!(
96 "{}{}{}",
97 $crate::color::fore("<", $color),
98 $crate::color::fore($arg, $color),
99 $crate::color::fore(">", $color),
100 )
101 }};
102 (@open, $arg:expr, $color:expr, @color=$fore:expr) => {{
103 format!(
104 "{}{}{}",
105 $crate::color::fore("<", $color),
106 $crate::color::fore($arg, $fore),
107 $crate::color::fore(">", $color),
108 )
109 }};
110
111 (@close, $arg:expr) => {{
112 $crate::tag!(@close, $arg, 7, @color=fore)
113 }};
114 (@close, $arg:expr, @color=auto) => {{
115 $crate::tag!(@close, $arg, 7, @color=auto)
116 }};
117 (@close, $arg:expr, @color=fore) => {{
118 $crate::tag!(@close, $arg, 7, @color=fore)
119 }};
120 (@close, $arg:expr, @color=$color:expr) => {{
121 $crate::tag!(@close, $arg, 7, @color=$color)
122 }};
123
124 (@close, $arg:expr, $color:expr) => {{
125 $crate::tag!(@close, $arg, $color, @color=$color)
126 }};
127 (@close, $arg:expr, $color:expr, @color=auto) => {{
128 let auto_color = $crate::color::from_display($arg) as usize;
129 format!(
130 "{}{}{}",
131 $crate::color::fore("</", $color),
132 $crate::color::fore($arg, auto_color),
133 $crate::color::fore(">", $color),
134 )
135 }};
136 (@close, $arg:expr, $color:expr, @color=fore) => {{
137 format!(
138 "{}{}{}",
139 $crate::color::fore("</", $color),
140 $crate::color::fore($arg, $color),
141 $crate::color::fore(">", $color),
142 )
143 }};
144 (@close, $arg:expr, $color:expr, @color=$fore:expr) => {{
145 format!(
146 "{}{}{}",
147 $crate::color::fore("</", $color),
148 $crate::color::fore($arg, $fore),
149 $crate::color::fore(">", $color),
150 )
151 }};
152
153
154 (@wrap, $tag:expr, $arg:expr) => {{
155 [
156 $crate::tag!(@open, $tag),
157 $crate::indent!($crate::color::fore($arg, 7)),
158 $crate::tag!(@close, $tag),
159 ].join("\n").to_string()
160 }};
161 (@wrap, $tag:expr, $arg:expr, @color=auto) => {{
162 [
163 $crate::tag!(@open, $tag, 7, @color=auto),
164 $crate::indent!($crate::color::auto($arg)),
165 $crate::tag!(@close, $tag, 7, @color=auto),
166 ].join("\n").to_string()
167
168 }};
169 (@wrap, $tag:expr, $arg:expr, @color=fore) => {{
170 [
171 $crate::tag!(@open, $tag, 7, @color=fore),
172 $crate::indent!($crate::color::fore($arg, 7)),
173 $crate::tag!(@close, $tag, 7, @color=fore),
174
175 ].join("\n").to_string()
176 }};
177 (@wrap, $tag:expr, $arg:expr, @color=$color:expr) => {{
178 [
179 $crate::tag!(@open, $arg, $color, @color=$color),
180 $crate::indent!($crate::color::fore($arg, $color)),
181 $crate::tag!(@close, $arg, $color, @color=$color),
182 ].join("\n").to_string()
183 }};
184
185 (@wrap, $tag:expr, $arg:expr, $color:expr) => {{
186 [
187 $crate::tag!(@open, $tag, $color, @color=$color),
188 $crate::indent!($crate::color::fore($arg, $color)),
189 $crate::tag!(@close, $tag, $color, @color=$color),
190 ].join("\n").to_string()
191 }};
192 (@wrap, $tag:expr, $arg:expr, $color:expr, @color=auto) => {{
193 let auto_tag_color = $crate::color::from_display($tag) as usize;
194 let auto_arg_color = $crate::color::from_display($arg) as usize;
195 [
196 $crate::tag!(@open, $tag, $color, @color=auto_tag_color),
197 $crate::indent!($crate::color::fore($arg, auto_arg_color)),
198 $crate::tag!(@close, $tag, $color, @color=auto_tag_color),
199 ].join("\n").to_string()
200 }};
201 (@wrap, $tag:expr, $arg:expr, $color:expr, @color=fore) => {{
202 [
203 $crate::tag!(@open, $tag, $color, @color=fore),
204 $crate::indent!($crate::color::fore($arg, $color)),
205 $crate::tag!(@close, $tag, $color, @color=fore),
206 ].join("\n").to_string()
207 }};
208 (@wrap, $tag:expr, $arg:expr, $color:expr, @color=$fore:expr) => {{
209 [
210 $crate::tag!(@open, $tag, $color, @color=$fore),
211 $crate::indent!($crate::color::fore($arg, $color)),
212 $crate::tag!(@close, $tag, $color, @color=$fore),
213 ].join("\n").to_string()
214 }};
215
216 ($arg:expr) => {{
261 $crate::tag!(@open, $arg, 7)
262 }};
263 ($arg:expr, $color:expr) => {{
264 $crate::tag!(@open, $arg, $color)
265 }};
266 ($arg:expr, @color=auto) => {{
267 $crate::tag!(@open, $arg, 7, @color=auto)
268 }};
269 ($arg:expr, @color=fore) => {{
270 $crate::tag!(@open, $arg, 7, @color=fore)
271 }};
272 ($arg:expr, @color=$fore:expr) => {{
273 $crate::tag!(@open, $arg, 7, @color=$fore)
274 }};
275 ($arg:expr, $color:expr, @color=$fore:expr) => {{
276 $crate::tag!(@open, $arg, $color, @color=$fore)
277 }};
278
279}
280
281#[macro_export]
283macro_rules! dbg {
284 ($arg:expr $(,)? ) => {{
285 eprintln!("{}", $crate::format_dbg_location!($arg));
286 $arg
287 }};
288 ($( $arg:expr ),* $(,)? ) => {{
289 eprintln!("{}", $crate::format_dbg_location!($($arg),*));
290 }};
291}
292
293#[macro_export]
294macro_rules! format_dbg {
295 ($arg:expr $(,)? ) => {{
296 $crate::indent!(
297 format!(
298 "{} = {}\n",
299 $crate::color::auto(stringify!(&$arg)),
300 $crate::color::auto(format!("{:#?}", &$arg))))
301
302 }};
303 ($( $arg:expr ),* $(,)? ) => {{
304 [$($crate::format_dbg!($arg)),*].join("\n")
305 }};
306}
307#[macro_export]
308macro_rules! format_dbg_location {
309 ($arg:expr $(,)? ) => {{
310 format!("{}", $crate::color::reset([$crate::location!(begin), $crate::format_dbg!($arg), $crate::location!(end)].join("\n")))
311 }};
312 ($( $arg:expr ),* $(,)? ) => {{
313 [$crate::location!(begin), $($crate::format_dbg!($arg)),*, $crate::location!(end)].join("\n")
314 }};
315}
316
317#[macro_export]
319macro_rules! indent {
320 ($indentation:literal, $obj:expr) => {{
321 format!("{}", $obj)
322 .lines()
323 .map(|line| format!("{}{}", " ".repeat($indentation), line))
324 .collect::<Vec<String>>()
325 .join("\n")
326 }};
327 ($obj:expr) => {{
328 $crate::indent!(4, $obj)
329 }};
330}
331#[macro_export]
333macro_rules! indent_objdump {
334 ($indentation:literal, $obj:expr) => {{
335 format!("{:#?}", $obj)
336 .lines()
337 .map(|line| format!("{}{}", " ".repeat($indentation), line))
338 .collect::<Vec<String>>()
339 .join("\n")
340 }};
341 ($obj:expr) => {{
342 $crate::indent_objdump!(4, $obj)
343 }};
344}
345
346#[macro_export]
348macro_rules! function_name {
349 () => {{
350 fn f() {}
351 fn type_name_of<T>(_: T) -> &'static str {
352 std::any::type_name::<T>()
353 }
354 let name = type_name_of(f);
355 let name = name
356 .strip_suffix("::f")
357 .unwrap()
358 .replace(format!("{}::", module_path!()).as_str(), "");
359 name
360 }};
361}
362
363#[macro_export]
365macro_rules! step {
366 ($text:expr $(,)?) => {{
367 $crate::step!(length=$crate::color::term_cols(), $text)
368 }};
369 (fg=$fg:expr, $text:expr $(,)?) => {{
370 let fg=$crate::color::wrap($fg as usize) as usize;
371 $crate::step!(bg=fg, fg=$crate::color::invert_ansi(fg), length=$crate::color::term_cols(), $text)
372 }};
373 (bg=$bg:expr, fg=$fg:expr, $text:expr $(,)?) => {{
374 let bg=$crate::color::wrap($bg as usize) as usize;
375 let fg=$crate::color::wrap($fg as usize) as usize;
376 $crate::step!(bg=bg, fg=fg, length=$crate::color::term_cols(), $text)
377 }};
378 (length=$length:expr, $text:expr $(,)?) => {{
379 let (bg, fg) = $crate::color::couple(line!() as usize);
380 $crate::step!(bg=bg, fg=fg, length=$length, $text)
381 }};
382 (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $text:expr $(,)?) => {{
383 let bg = $crate::color::wrap($bg as usize) as usize;
384 let fg = $crate::color::wrap($fg as usize) as usize;
385
386 let text = $text.to_string();
387 let bar = $crate::color::ansi(
388 " ".repeat($length),
389 $fg as usize,
390 $bg as usize,
391 );
392 eprintln!(
393 "\n{}",
394 [
395 bar.clone(),
396 $crate::color::ansi(
397 $crate::color::pad_columns(
398 [
399 $crate::function_name!(),
400 [
401 file!().to_string(),
402 line!().to_string(),
403 ].join(":")
404 ].join(" ").to_string()
405 ),
406 $fg as usize,
407 $bg as usize,
408 ),
409 $crate::color::ansi(
410 $crate::color::pad_columns(
411 if text.is_empty() { String::new() } else { format!("{}", text) }
412 ),
413 $bg as usize,
414 $fg as usize,
415 ),
416 bar.clone(),
417 ].join("\n")
418 );
419 }};
420 (length=$length:expr, $text:expr, $( $arg:expr ),* $(,)? ) => {{
421 $crate::step!(length=$length, format_args!($text, $($arg,)*))
422 }};
423 () => {{
424 $crate::step!("")
425 }};
426}
427#[macro_export]
429macro_rules! step_dbg {
430 (bg=$bg:expr, fg=$fg:expr, length=$length:expr, $($arg:expr),* $(,)?) => {{
431 let bg=$crate::color::wrap($bg as usize);
432 let fg=$crate::color::wrap($fg as usize);
433 let text = format!("{}{}", $crate::reset(""), [
434 $($crate::indent!(format!("{} = {}", $crate::color::auto(stringify!($arg)), $crate::color::auto(format!("{:#?}", $arg))))),*
435 ].join("\n"));
436 $crate::step!(bg=bg, fg=fg, length=$length, text);
437 }};
438 (bg=$bg:expr, fg=$fg:expr, $($arg:expr),* $(,)?) => {{
439 let bg=$crate::color::wrap($bg as usize);
440 let fg=$crate::color::wrap($fg as usize);
441 $crate::step_dbg!(bg=bg, fg=fg, length=$crate::color::term_cols(), $($arg),*)
442 }};
443 (fg=$fg:expr, $($arg:expr),* $(,)?) => {{
444 let fg=$crate::color::wrap($fg as usize) as usize;
445 $crate::step_dbg!(bg=fg, fg=$crate::color::invert_ansi(fg), length=$crate::color::term_cols(), $($arg),*)
446 }};
447 ($($arg:expr),* $(,)?) => {{
448 let fg=$crate::color::wrap(line!() as usize) as usize;
449 $crate::step_dbg!(bg=fg, fg=$crate::color::invert_ansi(fg), length=$crate::color::term_cols(), $($arg),*)
450 }};
451 () => {{
452 $crate::step!("")
453 }};
454}
455
456#[macro_export]
458macro_rules! admonition {
459 ($color:literal, $message:expr) => {
460 $crate::admonition!($color, "{}", $message);
461 };
462 ($color:literal, $title:literal, $message:expr) => {
463 $crate::admonition!($color, title=$title, $message);
464 };
465
466 ($color:literal, title=$title:literal, $message:expr) => {
467 $crate::admonition!($color, title=$title, "{}", $message);
468 };
469 ($color:literal, title=$title:literal, $format:literal, $($arg:expr),* $(,)?) => {{
470 use crate::color;
471 eprintln!(
472 "\n{}",
473 [
474 color::ansi(
475 format!("{}:{} {}", crate::function_name!(), line!(), $title),
476 color::invert_ansi($color).into(),
477 $color,
478 ),
479 color::ansi(
480 format!($format, $($arg),*),
481 $color,
482 color::invert_ansi($color).into(),
483 )
484 ]
485 .join(" ")
486 );
487 }};
488 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {{
489 use crate::color;
490 eprintln!(
491 "\n{}",
492 [
493 color::ansi(
494 format!("{}:{}", crate::function_name!(), line!()),
495 color::invert_ansi($color).into(),
496 $color,
497 ),
498 color::ansi(
499 format!($format, $($arg),*),
500 $color,
501 color::invert_ansi($color).into(),
502 )
503 ]
504 .join(" ")
505 );
506 }};
507}
508
509#[macro_export]
511macro_rules! warn {
512 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
513 $crate::admonition!($color, title="WARNING", $format, $($arg),*);
514 };
515 ($color:literal, $message:expr) => {
516 $crate::admonition!($color, title="WARNING", $message);
517 };
518 ($message:expr) => {
519 $crate::warn!(220, $message);
520 };
521}
522
523#[macro_export]
525macro_rules! info {
526 ($color:literal, $format:literal, $($arg:expr),* $(,)?) => {
527 $crate::admonition!($color, title="INFO", $format, $($arg),*);
528 };
529 ($color:literal, $message:expr) => {
530 $crate::admonition!($color, title="INFO", $message);
531 };
532 ($message:expr) => {
533 $crate::info!(74, $message);
534 };
535}
536
537#[macro_export]
539macro_rules! format_byte {
540 (hex_only, $byte:expr $(,)? ) => {{
541 use $crate::color::{auto, fore, from_byte, pad};
542 let color = $crate::color::from_byte($byte);
543 $crate::color::fore(format!("0x{:02x}", $byte), color.into())
544 }};
545 (hex, $byte:expr $(,)? ) => {{
546 use $crate::color::{auto, fore, from_bytes, pad};
547 let color = $crate::color::from_bytes(&[$byte]);
548 [
549 $crate::color::fore(format!("0x{:02x}", $byte), color.into()),
550 if $byte < 127 {
551 $crate::color::fore(
552 format!("{:#?}", char::from($byte).to_string()),
553 color.into(),
554 )
555 } else {
556 String::new()
557 },
558 ]
559 .iter()
560 .filter(|c| !c.is_empty())
561 .map(String::from)
562 .collect::<Vec<String>>()
563 .join(" => ")
564 }};
565 (bin, $byte:expr $(,)? ) => {{
566 use $crate::color::{auto, fore, from_bytes, pad};
567 let color = $crate::color::from_bytes(&[$byte]);
568 [
569 $crate::color::fore(format!("0b{:08b}", $byte), color.into()),
570 if $byte < 127 {
571 $crate::color::fore(
572 format!("{:#?}", char::from($byte).to_string()),
573 color.into(),
574 )
575 } else {
576 String::new()
577 },
578 ]
579 .iter()
580 .filter(|c| !c.is_empty())
581 .map(String::from)
582 .collect::<Vec<String>>()
583 .join(" => ")
584 }};
585 ($byte:expr $(,)? ) => {{
586 use $crate::color::{auto, fore, from_bytes, pad};
587 let color = $crate::color::from_bytes(&[$byte]);
588 [
589 $crate::color::fore(format!("0x{:02x}", $byte), color.into()),
590 $crate::color::fore(format!("0b{:08b}", $byte), color.into()),
591 $crate::color::fore(format!("{:#?}", $byte), color.into()),
592 if $byte < 127 {
593 $crate::color::fore(
594 format!("{:#?}", char::from($byte).to_string()),
595 color.into(),
596 )
597 } else {
598 String::new()
599 },
600 ]
601 .iter()
602 .filter(|c| !c.is_empty())
603 .map(String::from)
604 .collect::<Vec<String>>()
605 .join(" => ")
606 }};
607}
608#[macro_export]
610macro_rules! dbg_byte {
611 ($byte:expr $(,)? ) => {{
612 use $crate::color::{auto, fore, from_display};
613 let color = $crate::color::from_display($byte);
614 $crate::step!(format!(
615 "{} = {}",
616 $crate::color::auto(stringify!($byte)),
617 $crate::format_byte!($byte)
618 ));
619 $byte
620 }};
621}
622
623#[macro_export]
625macro_rules! dbg_bytes {
626 ($slice:expr $(,)? ) => {{
627 use $crate::color::{auto, back, fore, from_display, pad};
628 $crate::step!($crate::indent!(format!(
629 "{} = {}",
630 $crate::color::auto(stringify!($slice)),
631 $crate::format_bytes!($slice)
632 )));
633 $slice
634 }};
635}
636#[macro_export]
638macro_rules! dbg_bytes_str {
639 ($slice:expr $(,)? ) => {{
640 use $crate::color::{auto, back, fore, from_display, pad};
641 use $crate::indent;
642 eprintln!(
643 "\n{}",
644 [
645 $crate::location!(begin),
646 String::new(),
647 $crate::color::auto(stringify!($slice)),
648 $crate::format_bytes_str!($slice),
649 String::new(),
650 $crate::location!(end),
651 ]
652 .join("\n")
653 );
654 $slice
655 }};
656}
657#[macro_export]
659macro_rules! dbg_bytes_if_str {
660 ($slice:expr $(,)? ) => {
661 if let Ok(c) = std::str::from_utf8($slice) {
662 $crate::dbg_bytes!($slice)
663 } else {
664 $slice
665 }
666 };
667}
668#[macro_export]
670macro_rules! format_bytes {
671 ($slice:expr $(,)? ) => {
672 $crate::format_bytes!($slice, " => ");
673 };
674 (hex, $slice:expr $(,)? ) => {
675 $crate::format_bytes!(hex, $slice, " => ");
676 };
677 (bin, $slice:expr $(,)? ) => {
678 $crate::format_bytes!(bin, $slice, " => ");
679 };
680 ($slice:expr, $sep:literal $(,)? ) => {{
681 [
682 format!(
683 "[\n{}]",
684 $slice
685 .iter()
686 .map(Clone::clone)
687 .map(|byte| format!(
688 "{}, // {}\n",
689 $crate::indent!($crate::format_byte!(byte)),
690 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
691 ))
692 .collect::<Vec<String>>()
693 .join("")
694 ),
695 format!("{} bytes", $slice.len()),
696 std::str::from_utf8($slice)
697 .map(|s| {
698 let chars = s.chars().collect::<Vec<char>>();
699 format!(
700 "\"{s}\" => {} chars => [{}]",
701 chars.len(),
702 chars
703 .iter()
704 .map(|c| format!("{c:?}"))
705 .collect::<Vec<String>>()
706 .join(", ")
707 )
708 })
709 .unwrap_or_default(),
710 ]
711 .iter()
712 .filter(|c| !c.is_empty())
713 .map(String::from)
714 .collect::<Vec<String>>()
715 .join($sep.to_string().as_str())
716 }};
717 (hex, $slice:expr, $sep:literal $(,)? ) => {{
718 [
719 format!(
720 "[\n{}]",
721 $slice
722 .iter()
723 .map(Clone::clone)
724 .map(|byte| format!(
725 "{}, // {}\n",
726 $crate::indent!($crate::format_byte!(hex, byte)),
727 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
728 ))
729 .collect::<Vec<String>>()
730 .join("")
731 ),
732 std::str::from_utf8($slice)
733 .map(|s| format!("{s:#?}"))
734 .unwrap_or_default(),
735 ]
736 .iter()
737 .filter(|c| !c.is_empty())
738 .map(String::from)
739 .collect::<Vec<String>>()
740 .join($sep.to_string().as_str())
741 }};
742 (bin, $slice:expr, $sep:literal $(,)? ) => {{
743 [
744 format!(
745 "[\n{}]",
746 $slice
747 .iter()
748 .map(Clone::clone)
749 .map(|byte| format!(
750 "{}, // {}\n",
751 $crate::indent!($crate::format_byte!(bin, byte)),
752 $crate::color::fore(format!("{:#?}", char::from(byte).to_string()), 237),
753 ))
754 .collect::<Vec<String>>()
755 .join("")
756 ),
757 std::str::from_utf8($slice)
758 .map(|s| format!("{s:#?}"))
759 .unwrap_or_default(),
760 ]
761 .iter()
762 .filter(|c| !c.is_empty())
763 .map(String::from)
764 .collect::<Vec<String>>()
765 .join($sep.to_string().as_str())
766 }};
767}
768
769#[macro_export]
771macro_rules! format_bytes_str {
772 ($slice:expr $(,)? ) => {
773 $crate::format_bytes_str!($slice, " => ");
774 };
775 ($slice:expr, $sep:literal $(,)? ) => {{
776 [
777 format!(
778 "[{}]",
779 $slice
780 .iter()
781 .map(Clone::clone)
782 .map(|byte| $crate::format_byte!(hex_only, byte))
783 .collect::<Vec<String>>()
784 .join(", ")
785 ),
786 std::str::from_utf8($slice)
787 .map(|s| format!("{s:#?}"))
788 .unwrap_or_default(),
789 ]
790 .iter()
791 .filter(|c| !c.is_empty())
792 .map(String::from)
793 .collect::<Vec<String>>()
794 .join($sep.to_string().as_str())
795 }};
796}