mod seconds;
mod minutes;
mod hours;
mod days_of_month;
mod months;
mod days_of_week;
mod years;
pub use self::seconds::Seconds;
pub use self::minutes::Minutes;
pub use self::hours::Hours;
pub use self::days_of_month::DaysOfMonth;
pub use self::months::Months;
pub use self::days_of_week::DaysOfWeek;
pub use self::years::Years;
use std::collections::btree_set;
use schedule::{Specifier, Ordinal, OrdinalSet};
use error::*;
use std::borrow::Cow;
use std::iter;
pub struct OrdinalIter<'a> {
set_iter: btree_set::Iter<'a, Ordinal>,
}
impl<'a> Iterator for OrdinalIter<'a> {
type Item = Ordinal;
fn next(&mut self) -> Option<Ordinal> {
self.set_iter.next().map(|ordinal| ordinal.clone()) }
}
pub trait TimeUnitField
where
Self: Sized,
{
fn from_ordinal_set(ordinal_set: OrdinalSet) -> Self;
fn name() -> Cow<'static, str>;
fn inclusive_min() -> Ordinal;
fn inclusive_max() -> Ordinal;
fn ordinals(&self) -> &OrdinalSet;
fn includes(&self, ordinal: Ordinal) -> bool {
self.ordinals().contains(&ordinal)
}
fn iter(&self) -> OrdinalIter {
OrdinalIter { set_iter: self.ordinals().iter() }
}
fn count(&self) -> u32 {
self.ordinals().len() as u32
}
fn from_ordinal(ordinal: Ordinal) -> Self {
Self::from_ordinal_set(iter::once(ordinal).collect())
}
fn supported_ordinals() -> OrdinalSet {
(Self::inclusive_min()..Self::inclusive_max() + 1).collect()
}
fn all() -> Self {
Self::from_ordinal_set(Self::supported_ordinals())
}
fn ordinal_from_name(name: &str) -> Result<Ordinal> {
bail!(ErrorKind::Expression(format!(
"The '{}' field does not support using names. '{}' \
specified.",
Self::name(),
name
)))
}
fn validate_ordinal(ordinal: Ordinal) -> Result<Ordinal> {
match ordinal {
i if i < Self::inclusive_min() => {
bail!(ErrorKind::Expression(format!(
"{} must be greater than or equal to {}. ('{}' \
specified.)",
Self::name(),
Self::inclusive_min(),
i
)))
}
i if i > Self::inclusive_max() => {
bail!(ErrorKind::Expression(format!(
"{} must be less than {}. ('{}' specified.)",
Self::name(),
Self::inclusive_max(),
i
)))
}
i => Ok(i),
}
}
fn ordinals_from_specifier(specifier: &Specifier) -> Result<OrdinalSet> {
use self::Specifier::*;
match *specifier {
All => Ok(Self::supported_ordinals()),
Point(ordinal) => Ok((&[ordinal]).iter().cloned().collect()),
NamedPoint(ref name) => {
Ok(
(&[Self::ordinal_from_name(name)?])
.iter()
.cloned()
.collect(),
)
}
Period(start, step) => {
let mut start = Self::validate_ordinal(start)?;
let mut res = Vec::new();
while start <= Self::inclusive_max() {
res.push(start);
start += step;
}
Ok(res.into_iter().collect())
}
Range(start, end) => {
match (Self::validate_ordinal(start), Self::validate_ordinal(end)) {
(Ok(start), Ok(end)) if start <= end => Ok((start..end + 1).collect()),
_ => {
bail!(ErrorKind::Expression(format!(
"Invalid range for {}: {}-{}",
Self::name(),
start,
end
)))
}
}
}
NamedRange(ref start_name, ref end_name) => {
let start = Self::ordinal_from_name(start_name)?;
let end = Self::ordinal_from_name(end_name)?;
match (Self::validate_ordinal(start), Self::validate_ordinal(end)) {
(Ok(start), Ok(end)) if start <= end => Ok((start..end + 1).collect()),
_ => {
bail!(ErrorKind::Expression(format!(
"Invalid named range for {}: {}-{}",
Self::name(),
start_name,
end_name
)))
}
}
}
}
}
}