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.rs155
1 files changed, 155 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..03d8fd3940
--- /dev/null
+++ b/third_party/rust/anyhow/src/fmt.rs
@@ -0,0 +1,155 @@
+use crate::chain::Chain;
+use crate::error::ErrorImpl;
+use crate::ptr::Ref;
+use core::fmt::{self, Debug, Write};
+
+impl ErrorImpl {
+ pub(crate) unsafe fn display(this: Ref<Self>, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", Self::error(this))?;
+
+ if f.alternate() {
+ for cause in Self::chain(this).skip(1) {
+ write!(f, ": {}", cause)?;
+ }
+ }
+
+ Ok(())
+ }
+
+ pub(crate) unsafe fn debug(this: Ref<Self>, f: &mut fmt::Formatter) -> fmt::Result {
+ let error = Self::error(this);
+
+ 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(any(backtrace, feature = "backtrace"))]
+ {
+ use crate::backtrace::BacktraceStatus;
+
+ let backtrace = Self::backtrace(this);
+ if let BacktraceStatus::Captured = backtrace.status() {
+ let mut backtrace = backtrace.to_string();
+ write!(f, "\n\n")?;
+ if backtrace.starts_with("stack backtrace:") {
+ // Capitalize to match "Caused by:"
+ backtrace.replace_range(0..1, "S");
+ } else {
+ // "stack backtrace:" prefix was removed in
+ // https://github.com/rust-lang/backtrace-rs/pull/286
+ writeln!(f, "Stack backtrace:")?;
+ }
+ backtrace.truncate(backtrace.trim_end().len());
+ write!(f, "{}", 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);
+ }
+}