Skip to main content

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