1pub use crate::parser::pricedb_parser::{pricedb_from_file, pricedb_from_str};
6pub use crate::parser::tackler_txns::GitInputSelector;
7pub use crate::parser::tackler_txns::git_to_txns;
8pub use crate::parser::tackler_txns::paths_to_txns;
9pub use crate::parser::tackler_txns::string_to_txns;
10use winnow::error::{ErrMode, FromExternalError};
11
12mod error;
13mod pricedb_parser;
14mod tackler_parser;
15mod tackler_txns;
16
17use crate::kernel::settings::Settings;
18use crate::parser::error::TacklerTxnError;
19use winnow::Stateful;
20
21pub(crate) mod parts;
22
23pub(crate) type Stream<'is> = Stateful<&'is str, &'is mut Settings>;
24
25pub(crate) fn make_semantic_error<
26 'is,
27 E: winnow::error::FromExternalError<Stream<'is>, TacklerTxnError>,
28>(
29 is: &mut Stream<'is>,
30 msg: &str,
31) -> ErrMode<E> {
32 ErrMode::from_external_error(is, TacklerTxnError::semantic_error(msg)).cut()
33}
34
35pub(crate) fn from_error<
36 'is,
37 E: winnow::error::FromExternalError<Stream<'is>, TacklerTxnError>,
38 SE: std::error::Error + ?Sized,
39>(
40 is: &mut Stream<'is>,
41 err: &SE,
42) -> ErrMode<E> {
43 ErrMode::from_external_error(
44 is,
45 TacklerTxnError::semantic_error(err.to_string().as_str()),
46 )
47 .cut()
48}
49
50#[inline]
60fn illegal_characters(c: char) -> bool {
61 c == ':' || c.is_whitespace()
62}
63
64fn is_valid_id_start_char(c: char) -> bool {
66 !(c.is_ascii_digit() || c == ':' || c == '-' || c == '_' || c == 'ยท' || c.is_whitespace())
67}
68
69fn is_valid_sub_id_start_char(c: char) -> bool {
71 c.is_numeric() || is_valid_id_start_char(c)
72}
73
74pub fn is_valid_id(token: &str) -> bool {
76 !token.is_empty()
77 && token.starts_with(is_valid_id_start_char)
78 && !token.contains(illegal_characters)
79}
80
81pub fn is_valid_sub_id(token: &str) -> bool {
83 !token.is_empty()
84 && token.starts_with(is_valid_sub_id_start_char)
85 && !token.contains(illegal_characters)
86}
87
88#[cfg(test)]
89mod tests;