• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lennart-k / ical-rs / #104

24 Jan 2026 06:17PM UTC coverage: 76.252% (-1.1%) from 77.303%
#104

push

lennart-k
fix tests

1294 of 1697 relevant lines covered (76.25%)

2.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.57
/src/parser/component.rs
1
use std::{borrow::Cow, marker::PhantomData};
2

3
use crate::{
4
    ContentLineParser, LineReader, ParserError,
5
    component::{Component, ComponentMut},
6
    parser::{BytesLines, ParserOptions},
7
};
8

9
pub struct ComponentParser<'a, C: Component, I: Iterator<Item = Cow<'a, [u8]>>> {
10
    line_parser: ContentLineParser<'a, I>,
11
    _t: PhantomData<C>,
12
    options: ParserOptions,
13
}
14

15
impl<'a, C: Component> ComponentParser<'a, C, BytesLines<'a>> {
16
    /// Return a new `ComponentParser` from a `Reader`.
17
    pub fn from_slice(slice: &'a [u8]) -> Self {
7✔
18
        let line_reader = LineReader::from_slice(slice);
8✔
19
        let line_parser = ContentLineParser::new(line_reader);
7✔
20

21
        ComponentParser {
22
            line_parser,
23
            _t: Default::default(),
8✔
24
            options: Default::default(),
7✔
25
        }
26
    }
27

28
    pub fn with_options(mut self, options: ParserOptions) -> Self {
3✔
29
        self.options = options;
3✔
30
        self
6✔
31
    }
32
}
33

34
impl<'a, C: Component, I: Iterator<Item = Cow<'a, [u8]>>> ComponentParser<'a, C, I> {
35
    /// Read the next line and check if it's a valid VCALENDAR start.
36
    #[inline]
37
    fn check_header(&mut self) -> Result<Option<()>, ParserError> {
7✔
38
        let line = match self.line_parser.next() {
8✔
39
            Some(val) => val.map_err(ParserError::ContentLineError)?,
7✔
40
            None => return Ok(None),
5✔
41
        };
42

43
        if line.name != "BEGIN"
16✔
44
            || line.value.is_none()
16✔
45
            || !C::NAMES.contains(&line.value.as_ref().unwrap().to_uppercase().as_str())
9✔
46
            || !line.params.is_empty()
7✔
47
        {
48
            return Err(ParserError::MissingHeader);
2✔
49
        }
50

51
        Ok(Some(()))
10✔
52
    }
53

54
    pub fn expect_one(mut self) -> Result<<C::Unverified as ComponentMut>::Verified, ParserError> {
3✔
55
        let item = self.next().ok_or(ParserError::EmptyInput)??;
12✔
56
        if self.next().is_some() {
7✔
57
            return Err(ParserError::TooManyComponents);
×
58
        }
59
        Ok(item)
4✔
60
    }
61
}
62

63
impl<'a, C: Component, I: Iterator<Item = Cow<'a, [u8]>>> Iterator for ComponentParser<'a, C, I> {
64
    type Item = Result<<C::Unverified as ComponentMut>::Verified, ParserError>;
65

66
    fn next(&mut self) -> Option<Self::Item> {
7✔
67
        match self.check_header() {
8✔
68
            Ok(res) => res?,
10✔
69
            Err(err) => return Some(Err(err)),
2✔
70
        };
71

72
        let mut comp = C::Unverified::default();
10✔
73
        let result = match comp.parse(&mut self.line_parser, &self.options) {
14✔
74
            Ok(_) => comp.build(None),
8✔
75
            Err(err) => Err(err),
2✔
76
        };
77

78
        #[cfg(all(feature = "test", not(feature = "bench")))]
79
        {
80
            // Run this for more test coverage
81
            if let Ok(comp) = result.as_ref() {
×
82
                let mutable = comp.clone().mutable();
×
83
                mutable.get_properties();
×
84
            }
85
        }
86

87
        Some(result)
7✔
88
    }
89
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc