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 usize,
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 usize,
34 }
35 )
36}
37
38struct Print {
39 print_fn_address: usize,
40}
41
42impl fmt::Debug for Print {
43 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
44 unsafe {
48 let mut print_fn_frame = 0;
49 let mut frame_count = 0;
50 backtrace::trace_unsynchronized(|frame| {
51 let found = frame.symbol_address() as usize == self.print_fn_address;
52 if found {
53 print_fn_frame = frame_count;
54 }
55 frame_count += 1;
56 !found
57 });
58
59 let mode = PrintFmt::Short;
60 let mut p = print_path;
61 let mut f = backtrace::BacktraceFmt::new(fmt, mode, &mut p);
62 f.add_context()?;
63 let mut result = Ok(());
64 let mut frame_count = 0;
65 backtrace::trace_unsynchronized(|frame| {
66 let skip = frame_count < print_fn_frame;
67 frame_count += 1;
68 if skip {
69 return true;
70 }
71
72 let mut frame_fmt = f.frame();
73 let mut any_symbol = false;
74 backtrace::resolve_frame_unsynchronized(frame, |symbol| {
75 any_symbol = true;
76 if let Err(e) = frame_fmt.symbol(frame, symbol) {
77 result = Err(e)
78 }
79 });
80 if !any_symbol {
81 if let Err(e) = frame_fmt.print_raw(frame.ip(), None, None, None) {
82 result = Err(e)
83 }
84 }
85 result.is_ok()
86 });
87 result?;
88 f.finish()
89 }
90 }
91}
92
93fn print_path(fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>) -> fmt::Result {
94 match path {
95 BytesOrWideString::Bytes(mut bytes) => loop {
96 match std::str::from_utf8(bytes) {
97 Ok(s) => {
98 fmt.write_str(s)?;
99 break;
100 },
101 Err(err) => {
102 fmt.write_char(std::char::REPLACEMENT_CHARACTER)?;
103 match err.error_len() {
104 Some(len) => bytes = &bytes[err.valid_up_to() + len..],
105 None => break,
106 }
107 },
108 }
109 },
110 BytesOrWideString::Wide(wide) => {
111 for c in std::char::decode_utf16(wide.iter().cloned()) {
112 fmt.write_char(c.unwrap_or(std::char::REPLACEMENT_CHARACTER))?
113 }
114 },
115 }
116 Ok(())
117}