arch_pkg_text/parse/
partial.rs

1/// Partially parse an input.
2pub trait PartialParse<Input>: Sized {
3    /// Error that stopped the parsing process.
4    type Error;
5
6    /// Parse an input until completion or when an error occurs.
7    ///
8    /// The complete or partial result can be recovered regardless of errors.
9    fn partial_parse(input: Input) -> PartialParseResult<Self, Self::Error>;
10}
11
12/// Partially parse an input with an issue handler.
13pub trait ParseWithIssues<Input, HandleIssue, Error>: Sized {
14    /// Parse an input until completion or when the issue handler returns an error.
15    ///
16    /// The complete or partial result can be recovered regardless of errors.
17    fn parse_with_issues(
18        input: Input,
19        handle_issue: HandleIssue,
20    ) -> PartialParseResult<Self, Error>;
21}
22
23/// Result of a parsing process that may or may not be complete.
24#[derive(Debug, Clone, Copy)]
25pub struct PartialParseResult<Parsed, Error> {
26    /// The result of the parsing process, either partial or complete.
27    parsed: Parsed,
28    /// Possible error encountered during parsing.
29    error: Option<Error>,
30}
31
32impl<Parsed, Error> PartialParseResult<Parsed, Error> {
33    /// Create a complete parse result.
34    pub fn new_complete(parsed: Parsed) -> Self {
35        PartialParseResult {
36            parsed,
37            error: None,
38        }
39    }
40
41    /// Create partial parse result.
42    pub fn new_partial(parsed: Parsed, error: Error) -> Self {
43        PartialParseResult {
44            parsed,
45            error: Some(error),
46        }
47    }
48
49    /// Return an `Ok` if there was no error.
50    ///
51    /// Otherwise, return an `Err`.
52    pub fn try_into_complete(self) -> Result<Parsed, Error> {
53        match self.error {
54            Some(error) => Err(error),
55            None => Ok(self.parsed),
56        }
57    }
58
59    /// Return both the parsed object and the error regardless of whether there was an error.
60    pub fn into_partial(self) -> (Parsed, Option<Error>) {
61        (self.parsed, self.error)
62    }
63
64    /// Return a reference to the partially parsed object.
65    pub fn parsed(&self) -> &'_ Parsed {
66        &self.parsed
67    }
68
69    /// Return a reference to the stored error if there was one.
70    pub fn error(&self) -> Option<&'_ Error> {
71        self.error.as_ref()
72    }
73
74    /// Whether there was an error.
75    pub fn has_error(&self) -> bool {
76        self.error.is_some()
77    }
78}
79
80impl<Parsed, Error> From<PartialParseResult<Parsed, Error>> for Result<Parsed, Error> {
81    fn from(value: PartialParseResult<Parsed, Error>) -> Self {
82        value.try_into_complete()
83    }
84}
85
86impl<Parsed, Error> From<PartialParseResult<Parsed, Error>> for (Parsed, Option<Error>) {
87    fn from(value: PartialParseResult<Parsed, Error>) -> Self {
88        value.into_partial()
89    }
90}
91
92impl<Parsed, Error> From<(Parsed, Option<Error>)> for PartialParseResult<Parsed, Error> {
93    fn from((parsed, error): (Parsed, Option<Error>)) -> Self {
94        PartialParseResult { parsed, error }
95    }
96}