use crate::error::TimecodeError;
use crate::timecode::Timecode;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TimeRange {
start: Timecode,
duration_frames: i64,
}
impl TimeRange {
pub fn new(start: Timecode, duration_frames: i64) -> Self {
Self {
start,
duration_frames,
}
}
pub fn from_start_end(start: Timecode, end: Timecode) -> Result<Self, TimecodeError> {
let diff = end.frame_diff(&start)?;
Ok(Self {
start,
duration_frames: diff,
})
}
pub fn start(&self) -> Timecode {
self.start
}
pub fn duration_frames(&self) -> i64 {
self.duration_frames
}
pub fn end(&self) -> Timecode {
self.start + self.duration_frames
}
pub fn contains(&self, tc: Timecode) -> bool {
if tc.rate() != self.start.rate() {
return false;
}
let f = tc.total_frames();
f >= self.start.total_frames() && f < self.start.total_frames() + self.duration_frames
}
pub fn overlaps(&self, other: &TimeRange) -> bool {
if self.start.rate() != other.start.rate() {
return false;
}
let s1 = self.start.total_frames();
let e1 = s1 + self.duration_frames;
let s2 = other.start.total_frames();
let e2 = s2 + other.duration_frames;
s1 < e2 && s2 < e1
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::framerate::FrameRate;
#[test]
fn basic_range() {
let start = Timecode::from_frames(0, FrameRate::Fps24);
let r = TimeRange::new(start, 240);
assert_eq!(r.end().total_frames(), 240);
}
#[test]
fn contains() {
let start = Timecode::from_frames(100, FrameRate::Fps24);
let r = TimeRange::new(start, 50);
assert!(r.contains(Timecode::from_frames(120, FrameRate::Fps24)));
assert!(!r.contains(Timecode::from_frames(150, FrameRate::Fps24)));
assert!(!r.contains(Timecode::from_frames(99, FrameRate::Fps24)));
}
#[test]
fn overlaps() {
let a = TimeRange::new(Timecode::from_frames(0, FrameRate::Fps24), 100);
let b = TimeRange::new(Timecode::from_frames(50, FrameRate::Fps24), 100);
let c = TimeRange::new(Timecode::from_frames(100, FrameRate::Fps24), 50);
assert!(a.overlaps(&b));
assert!(!a.overlaps(&c));
}
#[test]
fn from_start_end() {
let start = Timecode::from_frames(100, FrameRate::Fps24);
let end = Timecode::from_frames(200, FrameRate::Fps24);
let r = TimeRange::from_start_end(start, end).unwrap();
assert_eq!(r.duration_frames(), 100);
}
}