summaryrefslogtreecommitdiffstats
path: root/third_party/rust/anyhow/src/fmt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/anyhow/src/fmt.rs')
-rw-r--r--third_party/rust/anyhow/src/fmt.rs149
1 files changed, 149 insertions, 0 deletions
diff --git a/third_party/rust/anyhow/src/fmt.rs b/third_party/rust/anyhow/src/fmt.rs
new file mode 100644
index 0000000000..16a82ba8d8
--- /dev/null
+++ b/third_party/rust/anyhow/src/fmt.rs
@@ -0,0 +1,149 @@
+use crate::chain::Chain;
+use crate::error::ErrorImpl;
+use core::fmt::{self, Debug, Write};
+
+impl ErrorImpl<()> {
+ pub(crate) fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.error())?;
+
+ if f.alternate() {
+ for cause in self.chain().skip(1) {
+ write!(f, ": {}", cause)?;
+ }
+ }
+
+ Ok(())
+ }
+
+ pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let error = self.error();
+
+ if f.alternate() {
+ return Debug::fmt(error, f);
+ }
+
+ write!(f, "{}", error)?;
+
+ if let Some(cause) = error.source() {
+ write!(f, "\n\nCaused by:")?;
+ let multiple = cause.source().is_some();
+ for (n, error) in Chain::new(cause).enumerate() {
+ writeln!(f)?;
+ let mut indented = Indented {
+ inner: f,
+ number: if multiple { Some(n) } else { None },
+ started: false,
+ };
+ write!(indented, "{}", error)?;
+ }
+ }
+
+ #[cfg(backtrace)]
+ {
+ use std::backtrace::BacktraceStatus;
+
+ let backtrace = self.backtrace();
+ if let BacktraceStatus::Captured = backtrace.status() {
+ let mut backtrace = backtrace.to_string();
+ if backtrace.starts_with("stack backtrace:") {
+ // Capitalize to match "Caused by:"
+ backtrace.replace_range(0..1, "S");
+ }
+ backtrace.truncate(backtrace.trim_end().len());
+ write!(f, "\n\n{}", backtrace)?;
+ }
+ }
+
+ Ok(())
+ }
+}
+
+struct Indented<'a, D> {
+ inner: &'a mut D,
+ number: Option<usize>,
+ started: bool,
+}
+
+impl<T> Write for Indented<'_, T>
+where
+ T: Write,
+{
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ for (i, line) in s.split('\n').enumerate() {
+ if !self.started {
+ self.started = true;
+ match self.number {
+ Some(number) => write!(self.inner, "{: >5}: ", number)?,
+ None => self.inner.write_str(" ")?,
+ }
+ } else if i > 0 {
+ self.inner.write_char('\n')?;
+ if self.number.is_some() {
+ self.inner.write_str(" ")?;
+ } else {
+ self.inner.write_str(" ")?;
+ }
+ }
+
+ self.inner.write_str(line)?;
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn one_digit() {
+ let input = "verify\nthis";
+ let expected = " 2: verify\n this";
+ let mut output = String::new();
+
+ Indented {
+ inner: &mut output,
+ number: Some(2),
+ started: false,
+ }
+ .write_str(input)
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn two_digits() {
+ let input = "verify\nthis";
+ let expected = " 12: verify\n this";
+ let mut output = String::new();
+
+ Indented {
+ inner: &mut output,
+ number: Some(12),
+ started: false,
+ }
+ .write_str(input)
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+
+ #[test]
+ fn no_digits() {
+ let input = "verify\nthis";
+ let expected = " verify\n this";
+ let mut output = String::new();
+
+ Indented {
+ inner: &mut output,
+ number: None,
+ started: false,
+ }
+ .write_str(input)
+ .unwrap();
+
+ assert_eq!(expected, output);
+ }
+}