outils/tree/generic/
error.rs

1//!
2//! `TreeError<Ix>` is the error type for the operations of the [`GenericForest`][1] trait.
3//!
4//! [1]: ../trait.GenericForest.html
5use std::error::Error;
6use std::fmt;
7use std::string::String;
8use super::*;
9
10/// Enum to refer to error situations that commonly occur in forest operations.
11#[derive(Clone, Debug)]
12pub enum TreeErrorType<Ix = DefaultIndexType> {
13    /// A node index was passed to an operation but did not refer to a valid node.
14    InvalidNodeIndex {
15        /// The node index that was passed to the operation.
16        node: NodeIndex<Ix>,
17    },
18    /// An operation is only defined for root nodes, but an invalid node index or a node index
19    /// referring to a non-tree node was passed to the operation.
20    ExpectedRootNode {
21        /// The node index that was passed to operation.
22        node: NodeIndex<Ix>,
23    },
24    /// An operation is only defined for forest nodes that are not part of the same forest tree,
25    /// but the nodes passed to this operation are already in a ancestor/descendant relation.
26    ExpectedNonAncestorNode {
27        /// The node that was passed to the operation as the new ancestor
28        new_ancestor: NodeIndex<Ix>,
29        /// The node that was passed to the operation as the new descendant
30        new_descendant: NodeIndex<Ix>,
31    },
32    /// Summary error type, which can be used in other error situations which do not have a
33    /// direct relation to defined operations of a forest.
34    OtherError {
35        /// Description of the particular error situation.
36        msg: String,
37    },
38}
39
40/// Error type that covers the error situations that commonly occur when manipulation tree or
41/// forest operations.
42///
43/// `TreeError` keeps a `TreeErrorType` describing the error as well as a `String` that can be
44/// used to store a description of the context in which the error has occured.
45#[derive(Clone, Debug)]
46pub struct TreeError<Ix = DefaultIndexType> {
47    context: String,
48    error: TreeErrorType<Ix>,
49}
50
51impl<Ix> TreeError<Ix> {
52    /// Construct a new `TreeError` of type `TreeErrorType::InvalidNodeIndex` referring to `node`
53    pub fn invalid_node_index(context: &str, node: NodeIndex<Ix>) -> Self {
54        TreeError {
55            context: String::from(context),
56            error: TreeErrorType::InvalidNodeIndex { node },
57        }
58    }
59
60    /// Construct a new `TreeError` of type `TreeErrorType::ExpectedRootNode` referring to `node`
61    pub fn expected_root_node(context: &str, node: NodeIndex<Ix>) -> Self {
62        TreeError {
63            context: String::from(context),
64            error: TreeErrorType::ExpectedRootNode { node },
65        }
66    }
67
68    /// Construct a new `TreeError` of type `TreeErrorType::ExpectedNonAncestorNode` referring to
69    /// `new_ancestor` and `new_descendant`.
70    pub fn expected_non_ancestor_node(
71        context: &str,
72        new_ancestor: NodeIndex<Ix>,
73        new_descendant: NodeIndex<Ix>,
74    ) -> Self {
75        TreeError {
76            context: String::from(context),
77            error: TreeErrorType::ExpectedNonAncestorNode {
78                new_ancestor,
79                new_descendant,
80            },
81        }
82    }
83
84    /// Construct a new `TreeError` of type `TreeErrorType::OtherType` with a custom message
85    /// `msg`describing the particular error situation.
86    pub fn other_error(context: &str, msg: &str) -> Self {
87        TreeError {
88            context: String::from(context),
89            error: TreeErrorType::OtherError {
90                msg: String::from(msg),
91            },
92        }
93    }
94}
95
96impl fmt::Display for TreeError {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        match self.error {
99            TreeErrorType::InvalidNodeIndex { node } => write!(
100                f,
101                "{}: the node index '{}' is invalid",
102                self.context,
103                node.index()
104            ),
105            TreeErrorType::ExpectedRootNode { node } => write!(
106                f,
107                "{}: the node '{}' must be a root node",
108                self.context,
109                node.index()
110            ),
111            TreeErrorType::ExpectedNonAncestorNode {
112                new_ancestor,
113                new_descendant,
114            } => write!(
115                f,
116                "{}: the new child node '{}' is an ancestor of the new parent node '{}'",
117                self.context,
118                new_ancestor.index(),
119                new_descendant.index()
120            ),
121            TreeErrorType::OtherError { ref msg } => write!(f, "{}: {}", self.context, msg),
122        }
123    }
124}
125
126impl Error for TreeError {
127    fn description(&self) -> &str {
128        match self.error {
129            TreeErrorType::InvalidNodeIndex { .. } => "Invalid node index",
130            TreeErrorType::ExpectedRootNode { .. } => "Expected root node",
131            TreeErrorType::ExpectedNonAncestorNode { .. } => "Expected non-ancestor node",
132            TreeErrorType::OtherError { .. } => "Other error",
133        }
134    }
135
136    fn cause(&self) -> Option<&dyn Error> {
137        None
138    }
139}