1use std::fmt;
2
3use crate::{Error, InternalServerError};
4
5pub struct DisplayError<'a>(&'a Error, bool);
6pub struct VerboseError<'a>(&'a Error);
7
8struct DisplayNum(Option<usize>);
9
10pub fn display_error(e: &Error, verbose: bool) -> DisplayError {
11 DisplayError(e, verbose)
12}
13pub fn display_error_verbose(e: &Error) -> VerboseError {
14 VerboseError(e)
15}
16
17impl fmt::Display for DisplayError<'_> {
18 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19 let DisplayError(ref e, verbose) = self;
20 write!(f, "{e:#}")?;
21 if e.is::<InternalServerError>() || *verbose {
22 if let Some(traceback) = e.server_traceback() {
23 write!(f, "\n Server traceback:")?;
24 for line in traceback.lines() {
25 write!(f, "\n {line}")?;
26 }
27 }
28 }
29 Ok(())
30 }
31}
32
33impl fmt::Display for DisplayNum {
34 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35 match self.0 {
36 Some(x) => x.fmt(f),
37 None => "?".fmt(f),
38 }
39 }
40}
41
42impl fmt::Display for VerboseError<'_> {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 let e = self.0;
45 writeln!(f, "Error type: {}", e.kind_debug())?;
46 writeln!(f, "Message: {e:#}")?;
47 let pstart = e.position_start();
48 let pend = e.position_end();
49 let line = e.line();
50 let column = e.column();
51 if [pstart, pend, line, column].iter().any(|x| x.is_some()) {
52 writeln!(
53 f,
54 "Span: {}-{}, line {}, column {}",
55 DisplayNum(pstart),
56 DisplayNum(pend),
57 DisplayNum(line),
58 DisplayNum(column)
59 )?;
60 }
61 if let Some(traceback) = e.server_traceback() {
62 writeln!(f, "Server traceback:")?;
63 for line in traceback.lines() {
64 writeln!(f, " {line}")?;
65 }
66 }
67
68 let attr = e.unknown_headers().collect::<Vec<_>>();
69 if !attr.is_empty() {
70 writeln!(f, "Other attributes:")?;
71 for (k, v) in attr {
72 writeln!(f, " 0x{k:04x}: {v:?}")?;
73 }
74 }
75 Ok(())
76 }
77}