Skip to main content

talw_timecode/
time_range.rs

1use crate::error::TimecodeError;
2use crate::timecode::Timecode;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub struct TimeRange {
6    start: Timecode,
7    duration_frames: i64,
8}
9
10impl TimeRange {
11    pub fn new(start: Timecode, duration_frames: i64) -> Self {
12        Self {
13            start,
14            duration_frames,
15        }
16    }
17
18    pub fn from_start_end(start: Timecode, end: Timecode) -> Result<Self, TimecodeError> {
19        let diff = end.frame_diff(&start)?;
20        Ok(Self {
21            start,
22            duration_frames: diff,
23        })
24    }
25
26    pub fn start(&self) -> Timecode {
27        self.start
28    }
29
30    pub fn duration_frames(&self) -> i64 {
31        self.duration_frames
32    }
33
34    pub fn end(&self) -> Timecode {
35        self.start + self.duration_frames
36    }
37
38    pub fn contains(&self, tc: Timecode) -> bool {
39        if tc.rate() != self.start.rate() {
40            return false;
41        }
42        let f = tc.total_frames();
43        f >= self.start.total_frames() && f < self.start.total_frames() + self.duration_frames
44    }
45
46    pub fn overlaps(&self, other: &TimeRange) -> bool {
47        if self.start.rate() != other.start.rate() {
48            return false;
49        }
50        let s1 = self.start.total_frames();
51        let e1 = s1 + self.duration_frames;
52        let s2 = other.start.total_frames();
53        let e2 = s2 + other.duration_frames;
54
55        s1 < e2 && s2 < e1
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62    use crate::framerate::FrameRate;
63
64    #[test]
65    fn basic_range() {
66        let start = Timecode::from_frames(0, FrameRate::Fps24);
67        let r = TimeRange::new(start, 240);
68        assert_eq!(r.end().total_frames(), 240);
69    }
70
71    #[test]
72    fn contains() {
73        let start = Timecode::from_frames(100, FrameRate::Fps24);
74        let r = TimeRange::new(start, 50);
75        assert!(r.contains(Timecode::from_frames(120, FrameRate::Fps24)));
76        assert!(!r.contains(Timecode::from_frames(150, FrameRate::Fps24)));
77        assert!(!r.contains(Timecode::from_frames(99, FrameRate::Fps24)));
78    }
79
80    #[test]
81    fn overlaps() {
82        let a = TimeRange::new(Timecode::from_frames(0, FrameRate::Fps24), 100);
83        let b = TimeRange::new(Timecode::from_frames(50, FrameRate::Fps24), 100);
84        let c = TimeRange::new(Timecode::from_frames(100, FrameRate::Fps24), 50);
85
86        assert!(a.overlaps(&b));
87        assert!(!a.overlaps(&c));
88    }
89
90    #[test]
91    fn from_start_end() {
92        let start = Timecode::from_frames(100, FrameRate::Fps24);
93        let end = Timecode::from_frames(200, FrameRate::Fps24);
94        let r = TimeRange::from_start_end(start, end).unwrap();
95        assert_eq!(r.duration_frames(), 100);
96    }
97}