1use std::borrow::Cow;
4
5use winnow::{
6 Parser,
7 ascii::Caseless,
8 error::ParserError,
9 stream::{AsBytes, Compare, Stream, StreamIsPartial},
10 token::take_until,
11};
12
13use error::CalendarParseError;
14
15use crate::parser::escaped::split_fold_prefix;
16
17pub mod component;
18pub mod config;
19pub mod error;
20pub mod escaped;
21pub mod parameter;
22pub mod primitive;
23pub mod property;
24pub mod rrule;
25
26pub trait InputStream
28where
29 Self: StreamIsPartial + Stream + Compare<char> + AsRef<[u8]>,
30 for<'a> Self: Compare<Caseless<&'a str>> + Compare<&'a str>,
31{
32 type Str: Clone + AsRef<str> + Into<String> + Into<Box<str>>;
33
34 fn try_into_str(slice: &Self::Slice) -> Result<Self::Str, CalendarParseError<Self::Slice>>;
35 fn try_into_string(slice: &Self::Slice) -> Result<String, CalendarParseError<Self::Slice>>;
36 fn as_bytes(slice: &Self::Slice) -> &[u8];
37 fn str_from_static_str(s: &'static str) -> Self::Str;
38
39 fn strip_line_fold_prefix(&mut self) -> usize;
42
43 fn next_contiguous_slice<E>(input: &mut Self) -> Result<Self::Slice, E>
47 where
48 E: ParserError<Self>;
49}
50
51impl InputStream for &str {
52 type Str = Self;
53
54 #[inline(always)]
55 fn try_into_str(slice: &Self::Slice) -> Result<Self::Str, CalendarParseError<Self::Slice>> {
56 Ok(slice)
57 }
58
59 #[inline(always)]
60 fn try_into_string(slice: &Self::Slice) -> Result<String, CalendarParseError<Self::Slice>> {
61 Ok(slice.to_string())
62 }
63
64 #[inline(always)]
65 fn as_bytes(slice: &Self::Slice) -> &[u8] {
66 slice.as_bytes()
67 }
68
69 #[inline(always)]
70 fn str_from_static_str(s: &'static str) -> Self::Str {
71 s
72 }
73
74 #[inline(always)]
75 fn strip_line_fold_prefix(&mut self) -> usize {
76 let (prefix, tail) = split_fold_prefix(self.as_bytes());
77 *self = str::from_utf8(tail).expect("tail represents a valid UTF-8 string slice");
78 prefix.len()
79 }
80
81 #[inline(always)]
82 fn next_contiguous_slice<E>(input: &mut Self) -> Result<Self::Slice, E>
83 where
84 E: ParserError<Self>,
85 {
86 let _ = input.strip_line_fold_prefix();
87
88 match take_until(0.., "\r\n").parse_next(input) {
89 Ok(slice) => Ok(slice),
90 Err(()) => Ok(input.finish()),
91 }
92 }
93}
94
95impl<'a> InputStream for &'a [u8] {
96 type Str = &'a str;
97
98 #[inline(always)]
99 fn try_into_str(slice: &Self::Slice) -> Result<Self::Str, CalendarParseError<Self::Slice>> {
100 std::str::from_utf8(slice).map_err(Into::into)
101 }
102
103 #[inline(always)]
104 fn try_into_string(slice: &Self::Slice) -> Result<String, CalendarParseError<Self::Slice>> {
105 Self::try_into_str(slice).map(ToString::to_string)
106 }
107
108 #[inline(always)]
109 fn as_bytes(slice: &Self::Slice) -> &[u8] {
110 slice
111 }
112
113 #[inline(always)]
114 fn str_from_static_str(s: &'static str) -> Self::Str {
115 s
116 }
117
118 #[inline(always)]
119 fn strip_line_fold_prefix(&mut self) -> usize {
120 let (prefix, tail) = split_fold_prefix(self);
121 *self = tail;
122 prefix.len()
123 }
124
125 #[inline(always)]
126 fn next_contiguous_slice<E>(input: &mut Self) -> Result<Self::Slice, E>
127 where
128 E: ParserError<Self>,
129 {
130 let _ = input.strip_line_fold_prefix();
131
132 match take_until(0.., "\r\n").parse_next(input) {
133 Ok(slice) => Ok(slice),
134 Err(()) => Ok(input.finish()),
135 }
136 }
137}
138
139impl<'a> InputStream for escaped::Escaped<'a> {
140 type Str = Cow<'a, str>;
141
142 #[inline(always)]
143 fn try_into_str(slice: &Self::Slice) -> Result<Self::Str, CalendarParseError<Self::Slice>> {
144 slice.try_into_cow_str().map_err(Into::into)
145 }
146
147 #[inline(always)]
148 fn try_into_string(slice: &Self::Slice) -> Result<String, CalendarParseError<Self::Slice>> {
149 Self::try_into_str(slice).map(|s| s.into_owned())
150 }
151
152 #[inline(always)]
153 fn as_bytes(slice: &Self::Slice) -> &[u8] {
154 slice.as_bytes()
155 }
156
157 #[inline(always)]
158 fn str_from_static_str(s: &'static str) -> Self::Str {
159 Cow::Borrowed(s)
160 }
161
162 #[inline(always)]
163 fn strip_line_fold_prefix(&mut self) -> usize {
164 let (prefix, tail) = split_fold_prefix(self.0);
165 self.0 = tail;
166 prefix.len()
167 }
168
169 #[inline(always)]
170 fn next_contiguous_slice<E>(input: &mut Self) -> Result<Self::Slice, E>
171 where
172 E: ParserError<Self>,
173 {
174 let _ = input.strip_line_fold_prefix();
178 let indices = <&[u8] as winnow::stream::FindSlice<_>>::find_slice(&input.0, "\r\n");
179
180 match indices {
181 Some(i) => Ok(input.next_slice(i.start)),
182 None => Ok(input.finish()),
183 }
184 }
185}