can_dbc/
parser.rs

1//!
2//! Parser module for DBC files using pest
3//!
4
5use can_dbc_pest::{Error as PestError, Pair, Pairs, Rule};
6
7pub type DbcResult<T> = Result<T, DbcError>;
8
9/// A helper function to decode cp1252 bytes, as DBC files are often encoded in cp1252.
10#[cfg(feature = "encodings")]
11#[must_use]
12pub fn decode_cp1252(bytes: &[u8]) -> Option<std::borrow::Cow<'_, str>> {
13    let (cow, _, had_errors) = crate::encodings::WINDOWS_1252.decode(bytes);
14    if had_errors {
15        None
16    } else {
17        Some(cow)
18    }
19}
20
21/// Error type for DBC parsing operations
22#[derive(Debug, Clone, PartialEq, thiserror::Error)]
23pub enum DbcError {
24    #[error("No more rules expected, but found: {0:?}")]
25    ExpectedEmpty(Rule),
26    #[error("Expected rule: {0:?}, found: {1:?}")]
27    ExpectedRule(Rule, Rule),
28    #[error("Expected one of these rules: {0:?}, found: {1:?}")]
29    ExpectedOneOfRules(Vec<Rule>, Rule),
30    #[error("Expected a quoted string or a number, found: {0:?}")]
31    ExpectedStrNumber(Rule),
32    #[error("Invalid Float value: '{0}'")]
33    InvalidFloat(String),
34    #[error("Invalid Int value: '{0}'")]
35    InvalidInt(String),
36    #[error("Invalid Uint value: '{0}'")]
37    InvalidUint(String),
38    #[error("Message ID out of range: {0}")]
39    MessageIdOutOfRange(u64),
40    #[error("Multiple multiplexors defined for a message")]
41    MultipleMultiplexors,
42    #[error("No more parsing rules available")]
43    NoMoreRules,
44    #[error("Feature not implemented: {0}")]
45    NotImplemented(&'static str),
46    #[error(transparent)]
47    Pest(Box<PestError<Rule>>),
48    #[error("Signal defined without an associated message")]
49    SignalWithoutMessage,
50    #[error("Unknown multiplex indicator: {0}")]
51    UnknownMultiplexIndicator(String),
52    #[error("Unknown rule: {0:?}")]
53    UnknownRule(Rule),
54    #[error("Invalid numeric value: '{0}'")]
55    InvalidNumericValue(String),
56}
57
58impl From<PestError<Rule>> for DbcError {
59    fn from(value: PestError<Rule>) -> Self {
60        Self::Pest(Box::new(value))
61    }
62}
63
64/// Helper function to get the next pair and validate its rule
65pub(crate) fn next<'a>(iter: &'a mut Pairs<Rule>) -> DbcResult<Pair<'a, Rule>> {
66    iter.next().ok_or(DbcError::NoMoreRules)
67}
68
69/// Helper function to get the next pair and validate its rule
70pub(crate) fn next_rule<'a>(
71    iter: &'a mut Pairs<Rule>,
72    expected: Rule,
73) -> DbcResult<Pair<'a, Rule>> {
74    next(iter).and_then(|pair| {
75        if pair.as_rule() == expected {
76            Ok(pair)
77        } else {
78            Err(DbcError::ExpectedRule(expected, pair.as_rule()))
79        }
80    })
81}
82
83pub(crate) fn next_optional_rule<'a>(
84    iter: &'a mut Pairs<Rule>,
85    expected: Rule,
86) -> Option<Pair<'a, Rule>> {
87    if let Some(pair) = iter.peek() {
88        if pair.as_rule() == expected {
89            return Some(iter.next().unwrap());
90        }
91    }
92    None
93}
94
95/// Helper function to get the next pair, ensure it matches the expected rule, and convert to string
96pub(crate) fn next_string(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<String> {
97    Ok(next_rule(iter, expected)?.as_str().to_string())
98}
99
100/// Helper function to get a single pair and validate its rule
101pub(crate) fn single_inner(pair: Pair<Rule>, expected: Rule) -> DbcResult<Pair<Rule>> {
102    let mut iter = pair.into_inner();
103    let pair = iter.next().ok_or(DbcError::NoMoreRules)?;
104    if pair.as_rule() != expected {
105        Err(DbcError::ExpectedRule(expected, pair.as_rule()))
106    } else if let Some(next) = iter.next() {
107        Err(DbcError::ExpectedEmpty(next.as_rule()))
108    } else {
109        Ok(pair)
110    }
111}
112
113/// Helper function to validate a pair's rule matches the expected rule
114pub(crate) fn validated(pair: Pair<Rule>, expected: Rule) -> DbcResult<Pair<Rule>> {
115    if pair.as_rule() == expected {
116        Ok(pair)
117    } else {
118        Err(DbcError::ExpectedRule(expected, pair.as_rule()))
119    }
120}
121
122pub(crate) fn validated_inner(pair: Pair<'_, Rule>, expected: Rule) -> DbcResult<Pairs<'_, Rule>> {
123    Ok(validated(pair, expected)?.into_inner())
124}
125
126/// Helper function to get a single pair, validate its rule, and convert to string
127pub(crate) fn single_inner_str(pair: Pair<Rule>, expected: Rule) -> DbcResult<String> {
128    Ok(single_inner(pair, expected)?.as_str().to_string())
129}
130
131/// Helper function to collect all remaining pairs of a specific rule type
132pub(crate) fn collect_all<'a, T: TryFrom<Pair<'a, Rule>, Error = DbcError>>(
133    iter: &mut Pairs<'a, Rule>,
134) -> DbcResult<Vec<T>> {
135    iter.map(TryInto::try_into).collect()
136}
137
138/// Helper function to collect all remaining pairs of a specific rule type
139pub(crate) fn collect_expected<'a, T: TryFrom<Pair<'a, Rule>, Error = DbcError>>(
140    iter: &mut Pairs<'a, Rule>,
141    expected: Rule,
142) -> DbcResult<Vec<T>> {
143    iter.map(|pair| {
144        if pair.as_rule() == expected {
145            pair.try_into()
146        } else {
147            Err(DbcError::ExpectedRule(expected, pair.as_rule()))
148        }
149    })
150    .collect()
151}
152
153/// Helper function to collect all remaining pairs of a specific rule type and convert to strings
154pub(crate) fn collect_strings(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<Vec<String>> {
155    iter.map(|pair| {
156        if pair.as_rule() == expected {
157            Ok(pair.as_str().to_string())
158        } else {
159            Err(DbcError::ExpectedRule(expected, pair.as_rule()))
160        }
161    })
162    .collect()
163}
164
165/// Helper function to ensure the iterator is empty (no more items)
166pub(crate) fn expect_empty(iter: &Pairs<Rule>) -> DbcResult<()> {
167    iter.peek()
168        .map_or(Ok(()), |v| Err(DbcError::ExpectedEmpty(v.as_rule())))
169}
170
171/// Helper function to extract string content from `quoted_str` rule
172pub(crate) fn inner_str(pair: Pair<Rule>) -> String {
173    // panics because pest grammar ensures this
174    next_rule(&mut pair.into_inner(), Rule::string)
175        .expect("string")
176        .as_str()
177        .to_string()
178}
179
180/// Helper function to parse an integer from a pest pair
181pub(crate) fn parse_int(pair: &Pair<Rule>) -> DbcResult<i64> {
182    let value = pair.as_str();
183    value
184        .parse::<i64>()
185        .map_err(|_| DbcError::InvalidInt(value.to_string()))
186}
187
188/// Helper function to parse an unsigned integer from a pest pair
189pub(crate) fn parse_uint(pair: &Pair<Rule>) -> DbcResult<u64> {
190    let value = pair.as_str();
191    value
192        .parse::<u64>()
193        .map_err(|_| DbcError::InvalidUint(value.to_string()))
194}
195
196/// Helper function to parse a float from a pest pair
197pub(crate) fn parse_float(pair: &Pair<Rule>) -> DbcResult<f64> {
198    let value = pair.as_str();
199    value
200        .parse::<f64>()
201        .map_err(|_| DbcError::InvalidFloat(value.to_string()))
202}
203
204/// Helper function to parse the next uint from the iterator
205pub(crate) fn parse_next_uint(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<u64> {
206    parse_uint(&next_rule(iter, expected)?)
207}
208
209/// Helper function to parse the next int from the iterator
210pub(crate) fn parse_next_int(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<i64> {
211    parse_int(&next_rule(iter, expected)?)
212}
213
214/// Helper function to parse the next float from the iterator
215pub(crate) fn parse_next_float(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<f64> {
216    parse_float(&next_rule(iter, expected)?)
217}
218
219/// Helper function to parse the next string from the iterator
220pub(crate) fn parse_next_inner_str(iter: &mut Pairs<Rule>, expected: Rule) -> DbcResult<String> {
221    Ok(inner_str(next_rule(iter, expected)?))
222}
223
224/// Helper to parse min/max values from a `min_max` rule
225pub(crate) fn parse_min_max_int(pair: Pair<Rule>) -> DbcResult<(i64, i64)> {
226    let mut pairs = pair.into_inner();
227
228    let min_val = parse_next_int(&mut pairs, Rule::minimum)?;
229    let max_val = parse_next_int(&mut pairs, Rule::maximum)?;
230    expect_empty(&pairs).expect("pest grammar ensures no extra items");
231
232    Ok((min_val, max_val))
233}
234
235/// Helper to parse min/max values from a `min_max` rule as floats
236pub(crate) fn parse_min_max_float(pair: Pair<Rule>) -> DbcResult<(f64, f64)> {
237    let mut pairs = pair.into_inner();
238
239    let min_val = parse_next_float(&mut pairs, Rule::minimum)?;
240    let max_val = parse_next_float(&mut pairs, Rule::maximum)?;
241    expect_empty(&pairs).expect("pest grammar ensures no extra items");
242
243    Ok((min_val, max_val))
244}