1use std::path::PathBuf;
5
6#[derive(Debug, thiserror::Error)]
8pub enum Error {
9 #[error("reading {path}: {source}")]
10 Io {
11 path: PathBuf,
12 #[source]
13 source: std::io::Error,
14 },
15
16 #[error("{path}: {source}")]
18 Config {
19 path: PathBuf,
20 #[source]
21 source: toml::de::Error,
22 },
23
24 #[error(
28 "externals.relations: \"{from}\" (under external \"{external}\") names no element in the surveyed model"
29 )]
30 UnknownRelationSource { external: String, from: String },
31
32 #[error(
34 "externals: id \"{id}\" is not an identifier (letters, digits and _, not starting with a digit, not a keyword)"
35 )]
36 InvalidExternalId { id: String },
37
38 #[error("element ids \"{first}\" and \"{second}\" both become the LikeC4 id \"{id}\"")]
41 DuplicateId {
42 id: String,
43 first: String,
44 second: String,
45 },
46
47 #[error("theme: \"{kind}\" is not an element kind of the surveyed model (have {have})")]
50 UnknownThemeKind { kind: String, have: String },
51
52 #[error("no supported stack detected at {root}")]
54 NoFrontend { root: PathBuf },
55
56 #[error("{frontend} front-end: {source}")]
58 Frontend {
59 frontend: String,
60 #[source]
61 source: Box<dyn std::error::Error + Send + Sync + 'static>,
62 },
63}
64
65pub type Result<T> = std::result::Result<T, Error>;
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn an_unknown_relation_source_names_the_external_and_the_from() {
73 let msg = Error::UnknownRelationSource {
74 external: "node_driver".into(),
75 from: "playwright_rs.nope".into(),
76 }
77 .to_string();
78 assert!(msg.contains("node_driver"), "{msg}");
79 assert!(msg.contains("playwright_rs.nope"), "{msg}");
80 }
81
82 #[test]
83 fn a_duplicate_id_names_both_originals_and_the_collision() {
84 let msg = Error::DuplicateId {
85 id: "foo_bar".into(),
86 first: "foo-bar".into(),
87 second: "foo_bar".into(),
88 }
89 .to_string();
90 assert!(
91 msg.contains("\"foo-bar\"") && msg.contains("\"foo_bar\""),
92 "{msg}"
93 );
94 }
95}