Skip to content

Commit

Permalink
simplify: lighter code to only manipulate selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
remi-dupre committed Feb 11, 2025
1 parent 78a5d2a commit 4ff8193
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 57 deletions.
1 change: 1 addition & 0 deletions opening-hours-syntax/src/rubik.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub(crate) type Selector1D<T> = PavingSelector<T, SelectorEmpty>;
pub(crate) type Selector2D<T, U> = PavingSelector<T, Selector1D<U>>;
pub(crate) type Selector3D<T, U, V> = PavingSelector<T, Selector2D<U, V>>;
pub(crate) type Selector4D<T, U, V, W> = PavingSelector<T, Selector3D<U, V, W>>;
pub(crate) type Selector5D<T, U, V, W, X> = PavingSelector<T, Selector4D<U, V, W, X>>;

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum PavingSelector<T, U> {
Expand Down
38 changes: 15 additions & 23 deletions opening-hours-syntax/src/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ use std::fmt::Display;
use std::sync::Arc;

use crate::rubik::{Paving, Paving5D};
use crate::simplify::{canonical_to_seq, seq_to_canonical, seq_to_canonical_day_selector};
use crate::simplify::{canonical_to_seq, ruleseq_to_selector, FULL_TIME};
use crate::sorted_vec::UniqueSortedVec;
use crate::ExtendedTime;

// OpeningHoursExpression

Expand All @@ -28,43 +27,36 @@ impl OpeningHoursExpression {
continue;
}

let Some(canonical) = seq_to_canonical(&head) else {
let Some(selector) = ruleseq_to_selector(&head) else {
simplified.push(head);
continue;
};

let mut selector_seq = vec![seq_to_canonical_day_selector(&head).unwrap()];
let mut canonical_seq = vec![canonical];
let mut selector_seq = vec![selector];

while let Some((selector, canonical)) = rules_queue
while let Some(selector) = rules_queue
.peek()
.filter(|r| r.operator == head.operator)
.filter(|r| r.kind == head.kind)
.filter(|r| r.comments == head.comments)
.and_then(|r| Some((seq_to_canonical_day_selector(r)?, seq_to_canonical(r)?)))
.and_then(ruleseq_to_selector)
{
rules_queue.next();
selector_seq.push(selector);
canonical_seq.push(canonical);
}

let mut union = Paving5D::default();

while let Some(canonical) = canonical_seq.pop() {
if let Some(prev_selector) = selector_seq.pop() {
union.set(
&prev_selector.dim([
ExtendedTime::new(0, 0).unwrap()..ExtendedTime::new(48, 0).unwrap()
]),
false,
);
}

union.union_with(canonical);
}
let paving = (selector_seq.into_iter().rev()).fold(
Paving5D::default(),
|mut union, selector| {
let full_day_selector = selector.unpack().1.clone().dim([FULL_TIME]);
union.set(&full_day_selector, false);
union.set(&selector, true);
union
},
);

simplified.extend(canonical_to_seq(
union,
paving,
head.operator,
head.kind,
head.comments,
Expand Down
64 changes: 31 additions & 33 deletions opening-hours-syntax/src/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::iter::{Chain, Once};
use std::ops::Range;
use std::sync::Arc;

use crate::rubik::{Paving, Paving5D, PavingSelector, Selector4D};
use crate::rubik::{Paving, Paving5D, PavingSelector, Selector4D, Selector5D};
use crate::rules::day::{DaySelector, MonthdayRange, WeekDayRange, WeekRange, YearRange};
use crate::rules::time::{Time, TimeSelector, TimeSpan};
use crate::rules::{RuleOperator, RuleSequence};
Expand All @@ -12,11 +12,11 @@ use crate::{ExtendedTime, RuleKind};

pub(crate) type Canonical = Paving5D<ExtendedTime, u8, u8, u8, u16>;

const FULL_YEARS: Range<u16> = u16::MIN..u16::MAX;
const FULL_MONTHDAYS: Range<u8> = 1..13;
const FULL_WEEKS: Range<u8> = 1..6;
const FULL_WEEKDAY: Range<u8> = 0..7;
const FULL_TIME: Range<ExtendedTime> =
pub(crate) const FULL_YEARS: Range<u16> = u16::MIN..u16::MAX;
pub(crate) const FULL_MONTHDAYS: Range<u8> = 1..13;
pub(crate) const FULL_WEEKS: Range<u8> = 1..6;
pub(crate) const FULL_WEEKDAY: Range<u8> = 0..7;
pub(crate) const FULL_TIME: Range<ExtendedTime> =
ExtendedTime::new(0, 0).unwrap()..ExtendedTime::new(48, 0).unwrap();

enum OneOrTwo<T> {
Expand Down Expand Up @@ -63,9 +63,7 @@ fn vec_with_default<T>(default: T, mut vec: Vec<T>) -> Vec<T> {
vec
}

pub(crate) fn seq_to_canonical_day_selector(
rs: &RuleSequence,
) -> Option<Selector4D<u8, u8, u8, u16>> {
pub(crate) fn ruleseq_to_day_selector(rs: &RuleSequence) -> Option<Selector4D<u8, u8, u8, u16>> {
let ds = &rs.day_selector;

let selector = PavingSelector::empty()
Expand Down Expand Up @@ -134,30 +132,30 @@ pub(crate) fn seq_to_canonical_day_selector(
Some(selector)
}

pub(crate) fn seq_to_canonical(rs: &RuleSequence) -> Option<Canonical> {
let selector = seq_to_canonical_day_selector(rs)?.dim(vec_with_default(
FULL_TIME,
(rs.time_selector.time.iter())
.flat_map(|time| match time {
TimeSpan { range, open_end: false, repeats: None } => {
let Time::Fixed(start) = range.start else {
return OneOrTwo::One(None);
};

let Time::Fixed(end) = range.end else {
return OneOrTwo::One(None);
};

split_inverted_range(start..end, FULL_TIME).map(Some)
}
_ => OneOrTwo::One(None),
})
.collect::<Option<Vec<_>>>()?,
));

let mut result = Paving5D::default();
result.set(&selector, true);
Some(result)
pub(crate) fn ruleseq_to_selector(
rs: &RuleSequence,
) -> Option<Selector5D<ExtendedTime, u8, u8, u8, u16>> {
Some(
ruleseq_to_day_selector(rs)?.dim(vec_with_default(
FULL_TIME,
(rs.time_selector.time.iter())
.flat_map(|time| match time {
TimeSpan { range, open_end: false, repeats: None } => {
let Time::Fixed(start) = range.start else {
return OneOrTwo::One(None);
};

let Time::Fixed(end) = range.end else {
return OneOrTwo::One(None);
};

split_inverted_range(start..end, FULL_TIME).map(Some)
}
_ => OneOrTwo::One(None),
})
.collect::<Option<Vec<_>>>()?,
)),
)
}

pub(crate) fn canonical_to_seq(
Expand Down
2 changes: 1 addition & 1 deletion opening-hours/src/opening_hours.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub const DATE_LIMIT: NaiveDateTime = {
/// Note that all big inner structures are immutable and wrapped by an `Arc`
/// so this is safe and fast to clone.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct OpeningHours<L: Localize = NoLocation> {
pub struct OpeningHours<L: Localize = NoLocationtoi> {
/// Rules describing opening hours
expr: Arc<OpeningHoursExpression>,
/// Evalutation context
Expand Down

0 comments on commit 4ff8193

Please sign in to comment.