1use thiserror::Error;
9
10pub type Result<T> = std::result::Result<T, NirError>;
12
13#[derive(Debug, Clone, PartialEq, Eq, Error)]
15#[non_exhaustive]
16pub enum NirError {
17 #[error("not implemented: {0}")]
21 Unimplemented(&'static str),
22
23 #[error("unknown node type: {0}")]
25 UnknownNodeType(String),
26
27 #[error("duplicate node: {0}")]
29 DuplicateNode(String),
30
31 #[error("missing node: {0}")]
33 MissingNode(String),
34
35 #[error("duplicate edge: ({0}, {1})")]
37 DuplicateEdge(String, String),
38
39 #[error("invalid graph: {0}")]
41 InvalidGraph(String),
42
43 #[error("unsupported version: {0}")]
45 UnsupportedVersion(String),
46
47 #[error("missing field: {0}")]
49 MissingField(String),
50
51 #[error("invalid tensor: {0}")]
53 InvalidTensor(String),
54
55 #[error(
57 "read allocation limit exceeded at {context}: limit {limit} bytes, used {used} bytes, requested {requested} bytes"
58 )]
59 ReadLimitExceeded {
60 context: String,
62 limit: usize,
64 used: usize,
66 requested: usize,
68 },
69
70 #[error("io error: {0}")]
75 Io(String),
76}
77
78#[cfg(feature = "hdf5")]
83impl From<hdf5::Error> for NirError {
84 fn from(err: hdf5::Error) -> Self {
85 Self::Io(err.to_string())
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn unimplemented_display() {
95 let err = NirError::Unimplemented("hdf5 read");
96 assert_eq!(err.to_string(), "not implemented: hdf5 read");
97 }
98
99 #[test]
100 fn unknown_node_type_display() {
101 let err = NirError::UnknownNodeType("CurrLIF".into());
102 assert_eq!(err.to_string(), "unknown node type: CurrLIF");
103 }
104
105 #[test]
106 fn duplicate_node_display() {
107 let err = NirError::DuplicateNode("lif".into());
108 assert_eq!(err.to_string(), "duplicate node: lif");
109 }
110
111 #[test]
112 fn missing_node_display() {
113 let err = NirError::MissingNode("missing".into());
114 assert_eq!(err.to_string(), "missing node: missing");
115 }
116
117 #[test]
118 fn duplicate_edge_display() {
119 let err = NirError::DuplicateEdge("a".into(), "b".into());
120 assert_eq!(err.to_string(), "duplicate edge: (a, b)");
121 }
122
123 #[test]
124 fn invalid_graph_display() {
125 let err = NirError::InvalidGraph("empty subgraph".into());
126 assert_eq!(err.to_string(), "invalid graph: empty subgraph");
127 }
128
129 #[test]
130 fn unsupported_version_display() {
131 let err = NirError::UnsupportedVersion("99.0".into());
132 assert_eq!(err.to_string(), "unsupported version: 99.0");
133 }
134
135 #[test]
136 fn missing_field_display() {
137 let err = NirError::MissingField("weight".into());
138 assert_eq!(err.to_string(), "missing field: weight");
139 }
140
141 #[test]
142 fn invalid_tensor_display() {
143 let err = NirError::InvalidTensor("shape product 4 != data len 3".into());
144 assert_eq!(
145 err.to_string(),
146 "invalid tensor: shape product 4 != data len 3"
147 );
148 }
149
150 #[test]
151 fn read_limit_display() {
152 let err = NirError::ReadLimitExceeded {
153 context: "lif.tau".into(),
154 limit: 1024,
155 used: 768,
156 requested: 512,
157 };
158 assert_eq!(
159 err.to_string(),
160 "read allocation limit exceeded at lif.tau: limit 1024 bytes, used 768 bytes, requested 512 bytes"
161 );
162 }
163
164 #[test]
165 fn io_display() {
166 let err = NirError::Io("unable to open file: model.nir".into());
167 assert_eq!(err.to_string(), "io error: unable to open file: model.nir");
168 }
169
170 #[test]
171 fn error_trait_implemented() {
172 let err: Box<dyn std::error::Error> = Box::new(NirError::Unimplemented("x"));
173 assert!(err.to_string().contains("not implemented"));
174 }
175}