///|
/// Half-open valid-time span. `None` means an unbounded right endpoint.
pub struct Span {
start : Int64
end : Int64?
}
///|
pub fn Span::new(start : Int64, end : Int64) -> Span raise TemporalError {
if end <= start {
raise InvalidSpan("end must be greater than start")
}
{ start, end: Some(end), }
}
///|
pub fn Span::open(start : Int64) -> Span {
{ start, end: None, }
}
///|
pub fn Span::start(self : Span) -> Int64 {
self.start
}
///|
pub fn Span::end(self : Span) -> Int64? {
self.end
}
///|
pub fn Span::contains(self : Span, instant : Int64) -> Bool {
instant >= self.start &&
(match self.end {
Some(end) => instant < end
None => true
})
}
///|
pub fn Span::overlaps(self : Span, other : Span) -> Bool {
let before_other_end = match other.end {
Some(end) => self.start < end
None => true
}
let other_before_end = match self.end {
Some(end) => other.start < end
None => true
}
before_other_end && other_before_end
}
///|
pub fn Span::intersection(self : Span, other : Span) -> Span? {
if !self.overlaps(other) {
return None
}
let start = if self.start > other.start { self.start } else { other.start }
let end = match (self.end, other.end) {
(Some(a), Some(b)) => Some(if a < b { a } else { b })
(Some(a), None) => Some(a)
(None, Some(b)) => Some(b)
(None, None) => None
}
Some({ start, end, })
}
///|
/// Whether two spans share a boundary but no interior.
pub fn Span::touches(self : Span, other : Span) -> Bool {
match (self.end, other.end) {
(Some(a), _) if a == other.start => true
(_, Some(b)) if b == self.start => true
_ => false
}
}