1use std::fmt;
2
3use thiserror::Error;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct SourceLocation {
11 pub line: u32,
12 pub col: u32,
13}
14
15impl fmt::Display for SourceLocation {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 write!(f, "{}:{}", self.line, self.col)
18 }
19}
20
21#[derive(Debug, Error)]
23pub enum SigmaParserError {
24 #[error("YAML parsing error: {0}")]
25 Yaml(#[from] serde_yaml::Error),
26
27 #[error("{}", format_with_location(.0, .1))]
28 Condition(String, Option<SourceLocation>),
29
30 #[error("Unknown modifier '{0}'")]
31 UnknownModifier(String),
32
33 #[error("Invalid field specification: {0}")]
34 InvalidFieldSpec(String),
35
36 #[error("Invalid rule: {0}")]
37 InvalidRule(String),
38
39 #[error("Missing required field '{0}'")]
40 MissingField(String),
41
42 #[error("Invalid detection: {0}")]
43 InvalidDetection(String),
44
45 #[error("Invalid correlation rule: {0}")]
46 InvalidCorrelation(String),
47
48 #[error("Invalid timespan '{0}'")]
49 InvalidTimespan(String),
50
51 #[error("Invalid value: {0}")]
52 InvalidValue(String),
53
54 #[error("Invalid collection action '{0}'")]
55 InvalidAction(String),
56
57 #[error("IO error: {0}")]
58 Io(#[from] std::io::Error),
59}
60
61impl SigmaParserError {
62 pub fn location(&self) -> Option<SourceLocation> {
64 match self {
65 SigmaParserError::Condition(_, loc) => *loc,
66 _ => None,
67 }
68 }
69}
70
71fn format_with_location(msg: &str, loc: &Option<SourceLocation>) -> String {
72 match loc {
73 Some(loc) => format!("Condition parse error at {loc}: {msg}"),
74 None => format!("Condition parse error: {msg}"),
75 }
76}
77
78pub type Result<T> = std::result::Result<T, SigmaParserError>;