1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::fmt;

use crate::{Error, InternalServerError};

pub struct DisplayError<'a>(&'a Error, bool);
pub struct VerboseError<'a>(&'a Error);

struct DisplayNum(Option<usize>);

pub fn display_error(e: &Error, verbose: bool) -> DisplayError {
    DisplayError(e, verbose)
}
pub fn display_error_verbose(e: &Error) -> VerboseError {
    VerboseError(e)
}

impl fmt::Display for DisplayError<'_> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let DisplayError(ref e, verbose) = self;
        write!(f, "{:#}", e)?;
        if e.is::<InternalServerError>() || *verbose {
            if let Some(traceback) = e.server_traceback() {
                write!(f, "\n  Server traceback:")?;
                for line in traceback.lines() {
                    write!(f, "\n      {}", line)?;
                }
            }
        }
        Ok(())
    }
}

impl fmt::Display for DisplayNum {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0 {
            Some(x) => x.fmt(f),
            None => "?".fmt(f),
        }
    }
}

impl fmt::Display for VerboseError<'_> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let e = self.0;
        writeln!(f, "Error type: {}", e.kind_debug())?;
        writeln!(f, "Message: {:#}", e)?;
        let pstart = e.position_start();
        let pend = e.position_end();
        let line = e.line();
        let column = e.column();
        if [pstart, pend, line, column].iter().any(|x| x.is_some()) {
            writeln!(
                f,
                "Span: {}-{}, line {}, column {}",
                DisplayNum(pstart),
                DisplayNum(pend),
                DisplayNum(line),
                DisplayNum(column)
            )?;
        }
        if let Some(traceback) = e.server_traceback() {
            writeln!(f, "Server traceback:")?;
            for line in traceback.lines() {
                writeln!(f, "    {}", line)?;
            }
        }

        let attr = e.unknown_headers().collect::<Vec<_>>();
        if !attr.is_empty() {
            writeln!(f, "Other attributes:")?;
            for (k, v) in attr {
                writeln!(f, "  0x{:04x}: {:?}", k, v)?;
            }
        }
        Ok(())
    }
}