1use std::fmt;
4use std::path::PathBuf;
5
6use crate::error::PackError;
7
8#[derive(Debug)]
11pub enum ScriptError {
12 Parse { line: usize, message: String },
14 UnknownKeyword {
18 line: usize,
19 keyword: String,
20 context: &'static str,
21 },
22 MissingOutput,
24 NoStructures,
26 UnclosedBlock(&'static str),
28 Io { path: PathBuf, message: String },
30 Pack(PackError),
32}
33
34impl fmt::Display for ScriptError {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 Self::Parse { line, message } => write!(f, "line {line}: {message}"),
38 Self::UnknownKeyword {
39 line,
40 keyword,
41 context,
42 } => write!(
43 f,
44 "line {line}: unknown keyword `{keyword}` in {context}. \
45 Silently dropping it risks wrong semantics (e.g. \
46 `pbc` that was ignored blew the cell grid); if this \
47 keyword should be accepted, add it to the parser",
48 ),
49 Self::MissingOutput => write!(f, "missing required `output` keyword"),
50 Self::NoStructures => write!(f, "no `structure` blocks found in script"),
51 Self::UnclosedBlock(kind) => write!(f, "unexpected EOF: unclosed `{kind}` block"),
52 Self::Io { path, message } => write!(f, "{}: {message}", path.display()),
53 Self::Pack(err) => write!(f, "packing failed: {err}"),
54 }
55 }
56}
57
58impl std::error::Error for ScriptError {
59 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
60 match self {
61 Self::Pack(err) => Some(err),
62 _ => None,
63 }
64 }
65}
66
67impl From<PackError> for ScriptError {
68 fn from(err: PackError) -> Self {
69 Self::Pack(err)
70 }
71}