]> git.proxmox.com Git - rustc.git/blob - vendor/anyhow/src/fmt.rs
New upstream version 1.46.0~beta.2+dfsg1
[rustc.git] / vendor / anyhow / src / fmt.rs
1 use crate::chain::Chain;
2 use crate::error::ErrorImpl;
3 use core::fmt::{self, Debug, Write};
4
5 impl ErrorImpl<()> {
6 pub(crate) fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
7 write!(f, "{}", self.error())?;
8
9 if f.alternate() {
10 for cause in self.chain().skip(1) {
11 write!(f, ": {}", cause)?;
12 }
13 }
14
15 Ok(())
16 }
17
18 pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
19 let error = self.error();
20
21 if f.alternate() {
22 return Debug::fmt(error, f);
23 }
24
25 write!(f, "{}", error)?;
26
27 if let Some(cause) = error.source() {
28 write!(f, "\n\nCaused by:")?;
29 let multiple = cause.source().is_some();
30 for (n, error) in Chain::new(cause).enumerate() {
31 writeln!(f)?;
32 let mut indented = Indented {
33 inner: f,
34 number: if multiple { Some(n) } else { None },
35 started: false,
36 };
37 write!(indented, "{}", error)?;
38 }
39 }
40
41 #[cfg(backtrace)]
42 {
43 use std::backtrace::BacktraceStatus;
44
45 let backtrace = self.backtrace();
46 if let BacktraceStatus::Captured = backtrace.status() {
47 let mut backtrace = backtrace.to_string();
48 write!(f, "\n\n")?;
49 if backtrace.starts_with("stack backtrace:") {
50 // Capitalize to match "Caused by:"
51 backtrace.replace_range(0..1, "S");
52 } else {
53 // "stack backtrace:" prefix was removed in
54 // https://github.com/rust-lang/backtrace-rs/pull/286
55 writeln!(f, "Stack backtrace:")?;
56 }
57 backtrace.truncate(backtrace.trim_end().len());
58 write!(f, "{}", backtrace)?;
59 }
60 }
61
62 Ok(())
63 }
64 }
65
66 struct Indented<'a, D> {
67 inner: &'a mut D,
68 number: Option<usize>,
69 started: bool,
70 }
71
72 impl<T> Write for Indented<'_, T>
73 where
74 T: Write,
75 {
76 fn write_str(&mut self, s: &str) -> fmt::Result {
77 for (i, line) in s.split('\n').enumerate() {
78 if !self.started {
79 self.started = true;
80 match self.number {
81 Some(number) => write!(self.inner, "{: >5}: ", number)?,
82 None => self.inner.write_str(" ")?,
83 }
84 } else if i > 0 {
85 self.inner.write_char('\n')?;
86 if self.number.is_some() {
87 self.inner.write_str(" ")?;
88 } else {
89 self.inner.write_str(" ")?;
90 }
91 }
92
93 self.inner.write_str(line)?;
94 }
95
96 Ok(())
97 }
98 }
99
100 #[cfg(test)]
101 mod tests {
102 use super::*;
103
104 #[test]
105 fn one_digit() {
106 let input = "verify\nthis";
107 let expected = " 2: verify\n this";
108 let mut output = String::new();
109
110 Indented {
111 inner: &mut output,
112 number: Some(2),
113 started: false,
114 }
115 .write_str(input)
116 .unwrap();
117
118 assert_eq!(expected, output);
119 }
120
121 #[test]
122 fn two_digits() {
123 let input = "verify\nthis";
124 let expected = " 12: verify\n this";
125 let mut output = String::new();
126
127 Indented {
128 inner: &mut output,
129 number: Some(12),
130 started: false,
131 }
132 .write_str(input)
133 .unwrap();
134
135 assert_eq!(expected, output);
136 }
137
138 #[test]
139 fn no_digits() {
140 let input = "verify\nthis";
141 let expected = " verify\n this";
142 let mut output = String::new();
143
144 Indented {
145 inner: &mut output,
146 number: None,
147 started: false,
148 }
149 .write_str(input)
150 .unwrap();
151
152 assert_eq!(expected, output);
153 }
154 }