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}