isothrum_compiler/
error.rs1use isoloom_spec::syntax::Problems;
4
5use crate::cables::LINK_BLOCK;
6
7pub type Result<T, E = Error> = std::result::Result<T, E>;
9
10#[derive(Debug, thiserror::Error)]
12#[non_exhaustive]
13pub enum Error {
14 #[error("link {link} refers to node `{node}`, which the lab doesn't have")]
16 UnknownNode {
17 link: usize,
19 node: String,
21 },
22 #[error("link {link} cables `{node}` to itself")]
24 SelfLink {
25 link: usize,
27 node: String,
29 },
30 #[error("port `{port}` of `{node}` already has a cable")]
32 PortInUse {
33 node: String,
35 port: String,
37 },
38 #[error("{0} cables don't fit in {LINK_BLOCK}")]
40 TooManyLinks(usize),
41 #[error("`{node}` is on LAN `{lan}`, which the lab doesn't have")]
43 UnknownLan {
44 node: String,
46 lan: String,
48 },
49 #[error("`{0}` is a name the cables use; call the LAN something else")]
51 ReservedLanName(String),
52 #[error("LAN `{lan}`: `{cidr}` isn't a block like 10.10.1.0/24")]
54 BadCidr {
55 lan: String,
57 cidr: String,
59 },
60 #[error("on LAN `{lan}`, `{first}` and `{second}` both ask for .{octet}")]
62 AddressTaken {
63 lan: String,
65 octet: u8,
67 first: String,
69 second: String,
71 },
72 #[error("LAN `{lan}` ({cidr}) has no free address left; use a larger block")]
74 LanFull {
75 lan: String,
77 cidr: String,
79 },
80 #[error("switch `{switch}` has the name of a LAN; rename one of them")]
82 SwitchNameTaken {
83 switch: String,
85 },
86 #[error("the name of port {port} of `{node}`")]
88 PortName {
89 node: String,
91 port: u16,
93 #[source]
95 source: isoloom_spec::Error,
96 },
97 #[error("writing the spec")]
99 Yaml(#[source] serde_yaml_ng::Error),
100 #[error("Isoloom doesn't read the compiled spec: {}", lines(.0))]
103 Unreadable(Problems),
104}
105
106fn lines(problems: &Problems) -> String {
108 problems.iter().map(isoloom_spec::syntax::Problem::line).collect::<Vec<_>>().join("; ")
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn a_spec_isoloom_does_not_read_says_each_problem() {
117 let problems = isoloom_spec::syntax::parse("version: 1\nname: x\nmachines:\n a:\n networks: { lan: x }\n b:\n color: red\n").unwrap_err();
118 assert!(problems.len() >= 2, "{problems:?}");
119 let said = Error::Unreadable(problems.clone()).to_string();
120 let expected: Vec<String> = problems.iter().map(isoloom_spec::syntax::Problem::line).collect();
121 assert_eq!(said, format!("Isoloom doesn't read the compiled spec: {}", expected.join("; ")));
122 }
123}