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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! Errors from validating stories that were successfully read.

use std::{error::Error, fmt};

use crate::{
    error::utils::{write_line_information, MetaData},
    knot::Address,
};

#[derive(Clone, Debug, PartialEq)]
/// Error for an invalid address in a story.
pub struct InvalidAddressError {
    /// Error variant.
    pub kind: InvalidAddressErrorKind,
    /// Information about the origin of the line containing this error.
    pub meta_data: MetaData,
}

#[derive(Clone, Debug, PartialEq)]
/// A divert (or other address) in the story is invalid.
pub enum InvalidAddressErrorKind {
    /// The address is not formatted correctly.
    BadFormat { line: String },
    /// The address does not reference a knot, stitch or variable in the story.
    UnknownAddress { name: String },
    /// Tried to validate an address but the given current knot did not exist in the system.
    UnknownCurrentAddress { address: Address },
    /// The address references a `Knot` that is not in the story.
    UnknownKnot { knot_name: String },
    /// The address references a `Stitch` that is not present in the current `Knot`.
    UnknownStitch {
        knot_name: String,
        stitch_name: String,
    },
    /// Tried to validate an address using an unvalidated current address.
    ValidatedWithUnvalidatedAddress {
        needle: String,
        current_address: Address,
    },
}

impl Error for InvalidAddressError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        Some(&self.kind)
    }
}

impl Error for InvalidAddressErrorKind {}

impl fmt::Display for InvalidAddressError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write_line_information(f, &self.meta_data)?;
        write!(f, "Invalid address: {}", self.kind)
    }
}

impl fmt::Display for InvalidAddressErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use InvalidAddressErrorKind::*;

        match self {
            BadFormat { line } => write!(f, "address was incorrectly formatted ('{}')", line),
            UnknownAddress { name } => write!(
                f,
                "could not find knot or variable with name '{}' in the story",
                name
            ),
            UnknownCurrentAddress { address } => write!(
                f,
                "during validation an address '{:?}' that is not in the system was used as
                 a current address",
                address
            ),
            UnknownKnot { knot_name } => {
                write!(f, "no knot with name '{}' in the story", knot_name)
            }
            UnknownStitch {
                knot_name,
                stitch_name,
            } => write!(
                f,
                "no stitch with name '{}' in knot '{}'",
                stitch_name, knot_name
            ),
            ValidatedWithUnvalidatedAddress {
                needle,
                current_address,
            } => write!(
                f,
                "during validating the raw address '{}' an unvalidated address '{:?}' was used",
                needle, current_address
            ),
        }
    }
}