1use crate::types::{Segment, SegmentOp, SegmentOps};
30
31#[derive(Debug, Clone)]
36pub struct SegmentSelector<'a> {
37 segments: Vec<&'a Segment>,
38}
39
40impl<'a> SegmentSelector<'a> {
41 pub(crate) fn new(segments: Vec<&'a Segment>) -> Self {
43 Self { segments }
44 }
45
46 pub fn count(&self) -> usize {
48 self.segments.len()
49 }
50
51 pub fn is_empty(&self) -> bool {
53 self.segments.is_empty()
54 }
55
56 pub fn segments(&self) -> &[&'a Segment] {
58 &self.segments
59 }
60
61 pub fn total_duration_ms(&self) -> u64 {
63 self.segments.iter().map(|s| s.duration_ms() as u64).sum()
64 }
65
66 pub fn total_frames(&self) -> usize {
68 self.segments.iter().map(|s| s.frame_count()).sum()
69 }
70
71 pub fn longer_than(self, ms: u32) -> Self {
77 let cs = (ms / 10) as u16;
78 Self {
79 segments: self
80 .segments
81 .into_iter()
82 .filter(|s| s.total_duration_cs > cs)
83 .collect(),
84 }
85 }
86
87 pub fn shorter_than(self, ms: u32) -> Self {
89 let cs = (ms / 10) as u16;
90 Self {
91 segments: self
92 .segments
93 .into_iter()
94 .filter(|s| s.total_duration_cs < cs)
95 .collect(),
96 }
97 }
98
99 pub fn duration_between(self, min_ms: u32, max_ms: u32) -> Self {
101 let min_cs = (min_ms / 10) as u16;
102 let max_cs = (max_ms / 10) as u16;
103 Self {
104 segments: self
105 .segments
106 .into_iter()
107 .filter(|s| s.total_duration_cs >= min_cs && s.total_duration_cs <= max_cs)
108 .collect(),
109 }
110 }
111
112 pub fn frames_gt(self, count: usize) -> Self {
114 Self {
115 segments: self
116 .segments
117 .into_iter()
118 .filter(|s| s.frame_count() > count)
119 .collect(),
120 }
121 }
122
123 pub fn frames_lt(self, count: usize) -> Self {
125 Self {
126 segments: self
127 .segments
128 .into_iter()
129 .filter(|s| s.frame_count() < count)
130 .collect(),
131 }
132 }
133
134 pub fn frames_eq(self, count: usize) -> Self {
136 Self {
137 segments: self
138 .segments
139 .into_iter()
140 .filter(|s| s.frame_count() == count)
141 .collect(),
142 }
143 }
144
145 pub fn filter<F>(self, predicate: F) -> Self
147 where
148 F: Fn(&Segment) -> bool,
149 {
150 Self {
151 segments: self.segments.into_iter().filter(|s| predicate(s)).collect(),
152 }
153 }
154
155 pub fn take(self, n: usize) -> Self {
157 Self {
158 segments: self.segments.into_iter().take(n).collect(),
159 }
160 }
161
162 pub fn skip(self, n: usize) -> Self {
164 Self {
165 segments: self.segments.into_iter().skip(n).collect(),
166 }
167 }
168
169 pub fn first(self) -> Self {
171 self.take(1)
172 }
173
174 pub fn last(self) -> Self {
176 Self {
177 segments: self.segments.into_iter().last().into_iter().collect(),
178 }
179 }
180
181 pub fn cap(&self, max_ms: u32) -> SegmentOps {
190 let max_cs = (max_ms / 10) as u16;
191 let mut ops = SegmentOps::new();
192
193 for segment in &self.segments {
194 if segment.total_duration_cs > max_cs {
195 ops.insert(segment.id, SegmentOp::Collapse { delay_cs: max_cs });
196 }
197 }
198
199 ops
200 }
201
202 pub fn collapse(&self, duration_ms: u32) -> SegmentOps {
204 let delay_cs = (duration_ms / 10) as u16;
205 let mut ops = SegmentOps::new();
206
207 for segment in &self.segments {
208 ops.insert(segment.id, SegmentOp::Collapse { delay_cs });
209 }
210
211 ops
212 }
213
214 pub fn remove(&self) -> SegmentOps {
216 let mut ops = SegmentOps::new();
217
218 for segment in &self.segments {
219 ops.insert(segment.id, SegmentOp::Remove);
220 }
221
222 ops
223 }
224
225 pub fn speed_up(&self, factor: f64) -> SegmentOps {
229 let mut ops = SegmentOps::new();
230
231 for segment in &self.segments {
232 ops.insert(
233 segment.id,
234 SegmentOp::Scale {
235 factor: 1.0 / factor,
236 },
237 );
238 }
239
240 ops
241 }
242
243 pub fn slow_down(&self, factor: f64) -> SegmentOps {
247 let mut ops = SegmentOps::new();
248
249 for segment in &self.segments {
250 ops.insert(segment.id, SegmentOp::Scale { factor });
251 }
252
253 ops
254 }
255
256 pub fn set_duration(&self, ms: u32) -> SegmentOps {
260 let total_cs = (ms / 10) as u16;
261 let mut ops = SegmentOps::new();
262
263 for segment in &self.segments {
264 ops.insert(segment.id, SegmentOp::SetDuration { total_cs });
265 }
266
267 ops
268 }
269
270 pub fn set_frame_delay(&self, ms: u32) -> SegmentOps {
272 let delay_cs = (ms / 10) as u16;
273 let mut ops = SegmentOps::new();
274
275 for segment in &self.segments {
276 ops.insert(segment.id, SegmentOp::SetFrameDelay { delay_cs });
277 }
278
279 ops
280 }
281
282 pub fn keep(&self) -> SegmentOps {
287 let mut ops = SegmentOps::new();
288
289 for segment in &self.segments {
290 ops.insert(segment.id, SegmentOp::Keep);
291 }
292
293 ops
294 }
295
296 pub fn scale(&self, factor: f64) -> SegmentOps {
300 let mut ops = SegmentOps::new();
301
302 for segment in &self.segments {
303 ops.insert(segment.id, SegmentOp::Scale { factor });
304 }
305
306 ops
307 }
308}
309
310pub trait SegmentOpsExt {
316 fn merge(&self, other: &SegmentOps) -> SegmentOps;
320
321 fn and(self, other: SegmentOps) -> SegmentOps;
323
324 fn merge_all(sets: &[&SegmentOps]) -> SegmentOps;
326}
327
328impl SegmentOpsExt for SegmentOps {
329 fn merge(&self, other: &SegmentOps) -> SegmentOps {
330 let mut merged = self.clone();
331 merged.extend(other.iter().map(|(k, v)| (*k, v.clone())));
332 merged
333 }
334
335 fn and(mut self, other: SegmentOps) -> SegmentOps {
336 self.extend(other);
337 self
338 }
339
340 fn merge_all(sets: &[&SegmentOps]) -> SegmentOps {
341 let mut merged = SegmentOps::new();
342 for ops in sets {
343 merged.extend(ops.iter().map(|(k, v)| (*k, v.clone())));
344 }
345 merged
346 }
347}
348
349#[cfg(test)]
350mod tests {
351 use super::*;
352 use std::ops::Range;
353
354 fn make_segment(id: usize, duration_cs: u16, frames: usize, is_static: bool) -> Segment {
355 Segment {
356 id,
357 frame_range: Range {
358 start: 0,
359 end: frames,
360 },
361 total_duration_cs: duration_cs,
362 avg_distance: if is_static { 0.0 } else { 5.0 },
363 is_static,
364 }
365 }
366
367 #[test]
368 fn test_filter_longer_than() {
369 let segments = [
370 make_segment(0, 100, 10, true),
371 make_segment(1, 50, 5, true),
372 make_segment(2, 200, 20, true),
373 ];
374 let refs: Vec<_> = segments.iter().collect();
375 let selector = SegmentSelector::new(refs);
376
377 let filtered = selector.longer_than(600); assert_eq!(filtered.count(), 2);
379 }
380
381 #[test]
382 fn test_cap_operation() {
383 let segments = [
384 make_segment(0, 100, 10, true), make_segment(1, 50, 5, true), make_segment(2, 200, 20, true), ];
388 let refs: Vec<_> = segments.iter().collect();
389 let selector = SegmentSelector::new(refs);
390
391 let ops = selector.cap(800); assert_eq!(ops.len(), 2);
395 assert!(matches!(
396 ops.get(&0),
397 Some(SegmentOp::Collapse { delay_cs: 80 })
398 ));
399 assert!(matches!(
400 ops.get(&2),
401 Some(SegmentOp::Collapse { delay_cs: 80 })
402 ));
403 }
404
405 #[test]
406 fn test_merge_ops() {
407 let mut ops1 = SegmentOps::new();
408 ops1.insert(0, SegmentOp::Keep);
409 ops1.insert(1, SegmentOp::Remove);
410
411 let mut ops2 = SegmentOps::new();
412 ops2.insert(1, SegmentOp::Collapse { delay_cs: 50 }); ops2.insert(2, SegmentOp::Remove);
414
415 let merged = ops1.merge(&ops2);
416
417 assert_eq!(merged.len(), 3);
418 assert!(matches!(merged.get(&0), Some(SegmentOp::Keep)));
419 assert!(matches!(
420 merged.get(&1),
421 Some(SegmentOp::Collapse { delay_cs: 50 })
422 ));
423 assert!(matches!(merged.get(&2), Some(SegmentOp::Remove)));
424 }
425}