1mod days_of_month;
2mod days_of_week;
3mod hours;
4mod minutes;
5mod months;
6mod seconds;
7mod years;
8
9pub use self::days_of_month::DaysOfMonth;
10pub use self::days_of_week::DaysOfWeek;
11pub use self::hours::Hours;
12pub use self::minutes::Minutes;
13pub use self::months::Months;
14pub use self::seconds::Seconds;
15pub use self::years::Years;
16
17use crate::error::*;
18use crate::ordinal::{Ordinal, OrdinalSet, Pattern, OrdinalList};
19use crate::specifier::{RootSpecifier, Specifier};
20use std::borrow::Cow;
21use std::collections::btree_set;
22use std::iter;
23use std::ops::RangeBounds;
24
25pub struct OrdinalIter<'a> {
26 set_iter: btree_set::Iter<'a, Ordinal>,
27}
28
29impl<'a> Iterator for OrdinalIter<'a> {
30 type Item = Ordinal;
31 fn next(&mut self) -> Option<Ordinal> {
32 self.set_iter.next().copied()
33 }
34}
35
36impl<'a> DoubleEndedIterator for OrdinalIter<'a> {
37 fn next_back(&mut self) -> Option<Self::Item> {
38 self.set_iter.next_back().copied()
39 }
40}
41
42pub struct OrdinalRangeIter<'a> {
43 range_iter: btree_set::Range<'a, Ordinal>,
44}
45
46impl<'a> Iterator for OrdinalRangeIter<'a> {
47 type Item = Ordinal;
48 fn next(&mut self) -> Option<Ordinal> {
49 self.range_iter.next().copied()
50 }
51}
52
53impl<'a> DoubleEndedIterator for OrdinalRangeIter<'a> {
54 fn next_back(&mut self) -> Option<Self::Item> {
55 self.range_iter.next_back().copied()
56 }
57}
58
59pub trait TimeUnitSpec {
92 fn includes(&self, ordinal: Ordinal) -> bool;
107
108 fn iter(&self) -> OrdinalIter<'_>;
127
128 fn range<R>(&self, range: R) -> OrdinalRangeIter<'_>
144 where
145 R: RangeBounds<Ordinal>;
146
147 fn count(&self) -> u32;
159
160 fn is_all(&self) -> bool;
173}
174
175impl<T> TimeUnitSpec for T
176where
177 T: TimeUnitField,
178{
179 fn includes(&self, ordinal: Ordinal) -> bool {
180 self.ordinals().contains(&ordinal)
181 }
182 fn iter(&self) -> OrdinalIter<'_> {
183 OrdinalIter {
184 set_iter: TimeUnitField::ordinals(self).iter(),
185 }
186 }
187 fn range<R>(&'_ self, range: R) -> OrdinalRangeIter<'_>
188 where
189 R: RangeBounds<Ordinal>,
190 {
191 OrdinalRangeIter {
192 range_iter: TimeUnitField::ordinals(self).range(range),
193 }
194 }
195 fn count(&self) -> u32 {
196 self.ordinals().len() as u32
197 }
198
199 fn is_all(&self) -> bool {
200 let max_supported_ordinals = Self::inclusive_max() - Self::inclusive_min() + 1;
201 self.ordinals().len() == max_supported_ordinals as usize
202 }
203}
204
205pub trait TimeUnitField
206where
207 Self: Sized,
208{
209 fn from_optional_ordinal_set(ordinal_set: Option<OrdinalSet>, pattern: Pattern, ordinal_list: OrdinalList) -> Self;
210 fn name() -> Cow<'static, str>;
211 fn inclusive_min() -> Ordinal;
212 fn inclusive_max() -> Ordinal;
213 fn ordinals(&self) -> &OrdinalSet;
214 fn ordinal_list(&self) -> &OrdinalList;
215 fn matching_pattern(&self) -> &str;
216
217 fn from_ordinal(ordinal: Ordinal, matching_pattern: String, ordinal_list: OrdinalList) -> Self {
218 Self::from_ordinal_set(iter::once(ordinal).collect(), matching_pattern, ordinal_list)
219 }
220
221 fn supported_ordinals() -> OrdinalSet {
222 (Self::inclusive_min()..Self::inclusive_max() + 1).collect()
223 }
224
225 fn all() -> Self {
226 Self::from_optional_ordinal_set(None, "value".to_string(), OrdinalList::new())
227 }
228
229 fn from_ordinal_set(ordinal_set: OrdinalSet, matching_pattern: String, ordinal_list: OrdinalList) -> Self {
230 Self::from_optional_ordinal_set(Some(ordinal_set), matching_pattern, ordinal_list)
231 }
232
233 fn ordinal_from_name(name: &str) -> Result<Ordinal, Error> {
234 Err(ErrorKind::Expression(format!(
235 "The '{}' field does not support using names. '{}' \
236 specified.",
237 Self::name(),
238 name
239 ))
240 .into())
241 }
242
243 fn validate_ordinal(ordinal: Ordinal) -> Result<Ordinal, Error> {
244 match ordinal {
246 i if i < Self::inclusive_min() => Err(ErrorKind::Expression(format!(
247 "{} must be greater than or equal to {}. ('{}' \
248 specified.)",
249 Self::name(),
250 Self::inclusive_min(),
251 i
252 ))
253 .into()),
254 i if i > Self::inclusive_max() => Err(ErrorKind::Expression(format!(
255 "{} must be less than {}. ('{}' specified.)",
256 Self::name(),
257 Self::inclusive_max(),
258 i
259 ))
260 .into()),
261 i => Ok(i),
262 }
263 }
264
265 fn ordinals_from_specifier(specifier: &Specifier) -> Result<(OrdinalSet, Pattern, OrdinalList), Error> {
266 use self::Specifier::*;
267 match specifier {
269 All => Ok((Self::supported_ordinals(), "value".to_string(), OrdinalList::new())),
270 Point(ordinal) => {
271 let mut os = OrdinalSet::new();
272 os.insert(*ordinal);
273 Ok((os, "value".to_string(), OrdinalList::new()))
274 },
275 Range(start, end) => {
276 match (Self::validate_ordinal(*start), Self::validate_ordinal(*end)) {
277 (Ok(start), Ok(end)) if start <= end => Ok(((start..end + 1).collect(), "value".to_string(), OrdinalList::new())),
278 _ => Err(ErrorKind::Expression(format!(
279 "Invalid range for {}: {}-{}",
280 Self::name(),
281 start,
282 end
283 ))
284 .into()),
285 }
286 }
287 NamedRange(ref start_name, ref end_name) => {
288 let start = Self::ordinal_from_name(start_name)?;
289 let end = Self::ordinal_from_name(end_name)?;
290 match (Self::validate_ordinal(start), Self::validate_ordinal(end)) {
291 (Ok(start), Ok(end)) if start <= end => Ok(((start..end + 1).collect(), "value".to_string(), OrdinalList::new())),
292 _ => Err(ErrorKind::Expression(format!(
293 "Invalid named range for {}: {}-{}",
294 Self::name(),
295 start_name,
296 end_name
297 ))
298 .into()),
299 }
300 }
301 MonthLast(pattern) => {
302 Ok((OrdinalSet::new(), pattern.to_string(), OrdinalList::new()))
303 }
304 MonthLastWithNum(num, pattern) => {
305 let mut os = OrdinalSet::new();
306 os.insert(*num);
307 Ok((os, pattern.to_string(), OrdinalList::new()))
308 },
309 MonthWeek(week, week_num, pattern) => {
310 let mut os = OrdinalList::new();
311 os.push(*week);
312 os.push(*week_num);
313 Ok((OrdinalSet::new(), pattern.to_string(), os))
314 },
315 }
316 }
317
318 fn ordinals_from_root_specifier(root_specifier: &RootSpecifier) -> Result<(OrdinalSet, Pattern, OrdinalList), Error> {
319 let (ordinals, pattern, ordinal_list) = match root_specifier {
320 RootSpecifier::Specifier(specifier) => Self::ordinals_from_specifier(specifier)?,
321 RootSpecifier::Period(_, 0) => Err(ErrorKind::Expression(format!("range step cannot be zero")))?,
322 RootSpecifier::Period(start, step) => {
323 let (base_set, pattern, ordinal_list) = match start {
324 Specifier::Point(start) => {
327 let start = Self::validate_ordinal(*start)?;
328 ((start..=Self::inclusive_max()).collect(), "value".to_string(), OrdinalList::new())
329 }
330 specifier => Self::ordinals_from_specifier(specifier)?,
331 };
332 (base_set.into_iter().step_by(*step as usize).collect(), pattern, ordinal_list)
333 }
334 RootSpecifier::NamedPoint(ref name) => ((&[Self::ordinal_from_name(name)?])
335 .iter()
336 .cloned()
337 .collect::<OrdinalSet>(), "value".to_string(), OrdinalList::new()),
338 };
339 Ok((ordinals, pattern, ordinal_list))
340 }
341}