1use std::fmt::{self, Write};
13
14use backtrace::{BytesOrWideString, PrintFmt};
15
16#[inline(never)]
17pub(crate) fn print(w: &mut dyn std::io::Write) -> Result<(), std::io::Error> {
18 write!(
19 w,
20 "{:?}",
21 Print {
22 print_fn_address: (print as *const ()).addr(),
23 }
24 )
25}
26
27#[cfg(target_env = "ohos")]
28pub(crate) fn print_ohos() {
29 log::error!(
31 "{:?}",
32 Print {
33 print_fn_address: (print as *const ()).addr(),
34 }
35 )
36}
37
38struct Print {
39 print_fn_address: usize,
41}
42
43impl fmt::Debug for Print {
44 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
45 unsafe {
49 let mut print_fn_frame = 0;
50 let mut frame_count = 0;
51 backtrace::trace_unsynchronized(|frame| {
52 let found = frame.symbol_address().addr() == self.print_fn_address;
53 if found {
54 print_fn_frame = frame_count;
55 }
56 frame_count += 1;
57 !found
58 });
59
60 let mode = PrintFmt::Short;
61 let mut p = print_path;
62 let mut f = backtrace::BacktraceFmt::new(fmt, mode, &mut p);
63 f.add_context()?;
64 let mut result = Ok(());
65 let mut frame_count = 0;
66 backtrace::trace_unsynchronized(|frame| {
67 let skip = frame_count < print_fn_frame;
68 frame_count += 1;
69 if skip {
70 return true;
71 }
72
73 let mut frame_fmt = f.frame();
74 let mut any_symbol = false;
75 backtrace::resolve_frame_unsynchronized(frame, |symbol| {
76 any_symbol = true;
77 if let Err(e) = frame_fmt.symbol(frame, symbol) {
78 result = Err(e)
79 }
80 });
81 if !any_symbol && let Err(e) = frame_fmt.print_raw(frame.ip(), None, None, None) {
82 result = Err(e)
83 }
84 result.is_ok()
85 });
86 result?;
87 f.finish()
88 }
89 }
90}
91
92fn print_path(fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>) -> fmt::Result {
93 match path {
94 BytesOrWideString::Bytes(mut bytes) => loop {
95 match std::str::from_utf8(bytes) {
96 Ok(s) => {
97 fmt.write_str(s)?;
98 break;
99 },
100 Err(err) => {
101 fmt.write_char(std::char::REPLACEMENT_CHARACTER)?;
102 match err.error_len() {
103 Some(len) => bytes = &bytes[err.valid_up_to() + len..],
104 None => break,
105 }
106 },
107 }
108 },
109 BytesOrWideString::Wide(wide) => {
110 for c in std::char::decode_utf16(wide.iter().cloned()) {
111 fmt.write_char(c.unwrap_or(std::char::REPLACEMENT_CHARACTER))?
112 }
113 },
114 }
115 Ok(())
116}