plantuml_parser/
container.rs

1use nom::Input;
2use std::sync::Arc;
3
4/// An intermediate representation to parse.
5///
6/// The [`ParseContainer`] has a shared pointer of the original [`String`] and the pair of sub-string position (`begin` and `end`),
7#[derive(Clone, Debug)]
8pub struct ParseContainer {
9    raw: Arc<String>,
10    begin: usize,
11    end: usize,
12}
13
14/// The error type to fail to parse.
15#[derive(thiserror::Error, Debug)]
16#[error("parse error: {0}")]
17pub struct ParseError(#[from] pub(crate) nom::Err<nom::error::Error<ParseContainer>>);
18
19/// The `Result` type for parsing process.
20pub type ParseResult<T> = Result<(ParseContainer, (ParseContainer, T)), ParseError>;
21
22impl ParseContainer {
23    /// Creates a new [`ParseContainer`] from the original string.
24    /// The inner positions are held in the entirety of the original string.
25    ///
26    /// # Examples
27    ///
28    /// ```
29    /// # use plantuml_parser::ParseContainer;
30    /// # use std::sync::Arc;
31    /// #
32    /// # fn main() {
33    /// let _ = ParseContainer::new(Arc::new("foo".to_string()));
34    /// # }
35    /// ```
36    pub fn new(raw: Arc<String>) -> Self {
37        let end = raw.len();
38        Self { raw, begin: 0, end }
39    }
40
41    /// Returns `true` if `self` has a length of zero
42    ///
43    /// # Examples
44    ///
45    /// ```
46    /// # use plantuml_parser::ParseContainer;
47    /// #
48    /// # fn main() {
49    /// let container = ParseContainer::from("");
50    /// assert!(container.is_empty());
51    /// # }
52    /// ```
53    ///
54    /// ```
55    /// # use plantuml_parser::ParseContainer;
56    /// # use std::sync::Arc;
57    /// #
58    /// # fn main() {
59    /// let container = ParseContainer::from("foo");
60    /// let (_rest, parsed) = container.split_at(0);
61    /// assert!(parsed.is_empty());
62    /// let (rest, _parsed) = container.split_at(container.len());
63    /// assert!(rest.is_empty());
64    /// # }
65    /// ```
66    pub fn is_empty(&self) -> bool {
67        self.as_str().is_empty()
68    }
69
70    /// Returns the length of `self`
71    ///
72    /// # Examples
73    ///
74    /// ```
75    /// # use plantuml_parser::ParseContainer;
76    /// #
77    /// # fn main() {
78    /// let container = ParseContainer::from("foo");
79    /// assert_eq!(container.len(), 3);
80    /// # }
81    /// ```
82    pub fn len(&self) -> usize {
83        self.as_str().len()
84    }
85
86    /// Returns a string slice of the sub-string
87    ///
88    /// # Examples
89    ///
90    /// ```
91    /// # use plantuml_parser::ParseContainer;
92    /// #
93    /// # fn main() {
94    /// let container = ParseContainer::from("foo");
95    /// let s: &str = container.as_str(); // Returns `&str`
96    /// assert_eq!(s, "foo");
97    /// # }
98    /// ```
99    pub fn as_str(&self) -> &str {
100        &self.raw[self.begin..self.end]
101    }
102
103    /// Splits into two sub-strings by `mid`
104    ///
105    /// * `mid` - A position to split.
106    ///
107    /// # Panics
108    ///
109    /// Panics if `mid` is past the end of the sub-string.
110    ///
111    /// # Examples
112    ///
113    /// ```
114    /// # use plantuml_parser::ParseContainer;
115    /// #
116    /// # fn main() {
117    /// let container = ParseContainer::from("Hello, World!");
118    /// let (rest, parsed) = container.split_at(7);
119    /// assert_eq!(rest, "World!");
120    /// assert_eq!(parsed, "Hello, ");
121    ///
122    /// let (rest, parsed) = container.split_at(0);
123    /// assert_eq!(rest, "Hello, World!");
124    /// assert_eq!(parsed, "");
125    ///
126    /// let (rest, parsed) = container.split_at(container.len());
127    /// assert_eq!(rest, "");
128    /// assert_eq!(parsed, "Hello, World!");
129    /// # }
130    /// ```
131    pub fn split_at(&self, mid: usize) -> (Self, Self) {
132        #[rustfmt::skip]
133        assert!(self.len() >= mid, "the `mid` is past the end: len = {}, mid = {}", self.len(), mid);
134
135        let rest = Self {
136            begin: self.begin + mid,
137            ..self.clone()
138        };
139
140        let parsed = Self {
141            end: self.begin + mid,
142            ..self.clone()
143        };
144
145        (rest, parsed)
146    }
147}
148
149impl PartialEq for ParseContainer {
150    fn eq(&self, rhs: &ParseContainer) -> bool {
151        self.as_str() == rhs.as_str()
152    }
153}
154
155impl PartialEq<&str> for ParseContainer {
156    fn eq(&self, rhs: &&str) -> bool {
157        self.as_str() == *rhs
158    }
159}
160
161impl PartialEq<ParseContainer> for &str {
162    fn eq(&self, rhs: &ParseContainer) -> bool {
163        *self == rhs.as_str()
164    }
165}
166
167impl std::borrow::Borrow<str> for ParseContainer {
168    fn borrow(&self) -> &str {
169        self.as_str()
170    }
171}
172
173impl std::fmt::Display for ParseContainer {
174    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
175        self.as_str().fmt(formatter)
176    }
177}
178
179impl From<&str> for ParseContainer {
180    fn from(s: &str) -> Self {
181        Self::new(Arc::new(s.into()))
182    }
183}
184
185impl From<String> for ParseContainer {
186    fn from(s: String) -> Self {
187        Self::new(Arc::new(s))
188    }
189}
190
191impl From<Vec<ParseContainer>> for ParseContainer {
192    fn from(x: Vec<ParseContainer>) -> Self {
193        x.as_slice().into()
194    }
195}
196
197impl From<&[ParseContainer]> for ParseContainer {
198    // TODO: move to `ParseContainer::from_vec() -> Result` because to check each element are neighboring
199    fn from(x: &[ParseContainer]) -> Self {
200        if x.is_empty() {
201            return Self::new(Arc::new("".into()));
202        }
203
204        let x0 = x.first().unwrap();
205        let len = x.iter().fold(0, |stack, item| stack + item.len());
206
207        Self {
208            end: x0.begin + len,
209            ..x0.clone()
210        }
211    }
212}
213
214impl<const N: usize> From<&[ParseContainer; N]> for ParseContainer {
215    fn from(x: &[ParseContainer; N]) -> Self {
216        x.as_slice().into()
217    }
218}
219
220impl Input for ParseContainer {
221    type Item = char;
222    type Iter = std::vec::IntoIter<Self::Item>;
223    type IterIndices = std::vec::IntoIter<(usize, Self::Item)>;
224
225    fn input_len(&self) -> usize {
226        self.len()
227    }
228
229    fn take(&self, index: usize) -> Self {
230        let end = self.begin + index;
231        assert!(end <= self.end);
232        Self {
233            end,
234            ..self.clone()
235        }
236    }
237
238    fn take_from(&self, index: usize) -> Self {
239        let begin = self.begin + index;
240        assert!(begin <= self.end);
241        Self {
242            begin,
243            ..self.clone()
244        }
245    }
246
247    fn take_split(&self, index: usize) -> (Self, Self) {
248        self.split_at(index)
249    }
250
251    fn position<P>(&self, predicate: P) -> Option<usize>
252    where
253        P: Fn(Self::Item) -> bool,
254    {
255        self.as_str().find(predicate)
256    }
257
258    fn iter_elements(&self) -> <Self as Input>::Iter {
259        self.as_str().chars().collect::<Vec<_>>().into_iter()
260    }
261
262    fn iter_indices(&self) -> <Self as Input>::IterIndices {
263        self.as_str().char_indices().collect::<Vec<_>>().into_iter()
264    }
265
266    fn slice_index(&self, count: usize) -> Result<usize, nom::Needed> {
267        self.as_str().slice_index(count)
268    }
269}
270
271/// wrap nom's parser
272macro_rules! wr {
273    ($func:expr) => {
274        |input: ParseContainer| {
275            use std::sync::Arc;
276
277            let input_str = input.as_str();
278            let (_rest, parsed) =
279                $func(input_str).map_err(|e: nom::Err<nom::error::Error<&str>>| {
280                    e.map_input(|x| ParseContainer::new(Arc::new(x.to_owned())))
281                })?;
282            let (rest, parsed) = input.split_at(parsed.len());
283            Ok((rest, parsed))
284        }
285    };
286}
287pub(crate) use wr;
288
289/// wrap crate's result ([`ParseResult`])
290macro_rules! wr2 {
291    ($func:expr) => {
292        |input: ParseContainer| $func(input).map_err(|e: $crate::ParseError| e.0)
293    };
294}
295pub(crate) use wr2;
296
297impl ParseError {
298    /// Returns [`ParseError`] contains [`nom::error::ErrorKind::Fail`].
299    pub fn fail(input: ParseContainer) -> Self {
300        Self(nom::Err::Error(nom::error::Error {
301            input,
302            code: nom::error::ErrorKind::Fail,
303        }))
304    }
305}
306
307#[cfg(test)]
308mod tests {
309    use super::*;
310
311    #[test]
312    fn test() {
313        let (rest0, parsed0) = ParseContainer::from("foobar").split_at(2);
314        println!("rest0 = {rest0}");
315        println!("parsed0 = {parsed0}");
316
317        assert_eq!(rest0, "obar");
318        assert_eq!(rest0.is_empty(), false);
319        assert_eq!(rest0.len(), 4);
320        assert_eq!(rest0.as_str(), "obar");
321        assert_eq!(parsed0, "fo");
322        assert_eq!(parsed0.is_empty(), false);
323        assert_eq!(parsed0.len(), 2);
324        assert_eq!(parsed0.as_str(), "fo");
325
326        let (rest1, parsed1) = rest0.split_at(3);
327        println!("rest1 = {rest1}");
328        println!("parsed1 = {parsed1}");
329
330        assert_eq!(rest1, "r");
331        assert_eq!(rest1.is_empty(), false);
332        assert_eq!(rest1.len(), 1);
333        assert_eq!(rest1.as_str(), "r");
334        assert_eq!(parsed1, "oba");
335        assert_eq!(parsed1.is_empty(), false);
336        assert_eq!(parsed1.len(), 3);
337        assert_eq!(parsed1.as_str(), "oba");
338
339        let (rest2, parsed2) = parsed1.split_at(3);
340        println!("rest2 = {rest2}");
341        println!("parsed2 = {parsed2}");
342
343        assert_eq!(rest2, "");
344        assert_eq!(rest2.is_empty(), true);
345        assert_eq!(rest2.len(), 0);
346        assert_eq!(rest2.as_str(), "");
347        assert_eq!(parsed2, "oba");
348        assert_eq!(parsed2.is_empty(), false);
349        assert_eq!(parsed2.len(), 3);
350        assert_eq!(parsed2.as_str(), "oba");
351
352        // It has the same `Arc<String>` after repeated division
353        assert!(Arc::ptr_eq(&rest0.raw, &rest1.raw));
354        assert!(Arc::ptr_eq(&rest0.raw, &rest2.raw));
355        assert!(Arc::ptr_eq(&rest0.raw, &parsed0.raw));
356        assert!(Arc::ptr_eq(&rest0.raw, &parsed1.raw));
357        assert!(Arc::ptr_eq(&rest0.raw, &parsed2.raw));
358    }
359
360    #[test]
361    fn test_split_at() {
362        let (rest, parsed) = ParseContainer::from("foobar").split_at(3);
363        println!("rest = {rest}");
364        println!("parsed = {parsed}");
365
366        assert_eq!(rest, "bar");
367        assert_eq!(parsed, "foo");
368    }
369
370    #[test]
371    #[should_panic(expected = "the `mid` is past the end: len = 0, mid = 1")]
372    fn test_panic_split_at_0() {
373        ParseContainer::from("").split_at(1);
374    }
375
376    #[test]
377    #[should_panic(expected = "the `mid` is past the end: len = 1, mid = 2")]
378    fn test_panic_split_at_1() {
379        let (_rest, parsed) = ParseContainer::from("test").split_at(1);
380        println!("parsed = {parsed}");
381        parsed.split_at(1); // not panic
382        parsed.split_at(2);
383    }
384
385    #[test]
386    #[should_panic(expected = "the `mid` is past the end: len = 3, mid = 4")]
387    fn test_panic_split_at_2() {
388        let (rest, _parsed) = ParseContainer::from("test").split_at(1);
389        println!("rest = {rest}");
390        rest.split_at(3); // not panic
391        rest.split_at(4);
392    }
393}