Skip to main content

braid_core/vendor/rle/
splitable_span.rs

1use std::ops::{Deref, DerefMut, Range};
2
3pub trait HasLength {
4    /// The number of child items in the entry. This is indexed with the size used in truncate.
5    fn len(&self) -> usize;
6
7    #[inline]
8    fn is_empty(&self) -> bool {
9        self.len() == 0
10    }
11}
12
13impl<V> HasLength for &V where V: HasLength {
14    fn len(&self) -> usize { (*self).len() }
15}
16
17pub trait SplitableSpanHelpers: Clone {
18    /// Split the entry, returning the part of the entry which was jettisoned. After truncating at
19    /// `pos`, self.len() == `pos` and the returned value contains the rest of the items.
20    ///
21    /// ```ignore
22    /// let initial_len = entry.len();
23    /// let rest = entry.truncate(truncate_at);
24    /// assert!(initial_len == truncate_at + rest.len());
25    /// ```
26    ///
27    /// `at` parameter must strictly obey *0 < at < entry.len()*
28    fn truncate_h(&mut self, at: usize) -> Self;
29
30    /// The inverse of truncate. This method mutably truncates an item, keeping all content from
31    /// at..item.len() and returning the item range from 0..at.
32    #[inline(always)]
33    fn truncate_keeping_right_h(&mut self, at: usize) -> Self {
34        let mut other = self.clone();
35        *self = other.truncate_h(at);
36        other
37    }
38
39    fn split(mut self, at: usize) -> (Self, Self) {
40        let remainder = self.truncate_h(at);
41        (self, remainder)
42    }
43}
44
45impl<T: SplitableSpanHelpers> SplitableSpanCtx for T {
46    type Ctx = ();
47
48    fn truncate_ctx(&mut self, at: usize, _ctx: &Self::Ctx) -> Self {
49        self.truncate_h(at)
50        // SplitableSpanHelpers::truncate(self, at)
51        // <self as SplitableSpanHelpers>::truncate(self, at)
52    }
53}
54
55pub trait SplitableSpanCtx: Clone {
56    type Ctx: ?Sized;
57
58    /// Split the entry, returning the part of the entry which was jettisoned. After truncating at
59    /// `pos`, self.len() == `pos` and the returned value contains the rest of the items.
60    ///
61    /// ```ignore
62    /// let initial_len = entry.len();
63    /// let rest = entry.truncate(truncate_at);
64    /// assert!(initial_len == truncate_at + rest.len());
65    /// ```
66    ///
67    /// `at` parameter must strictly obey *0 < at < entry.len()*
68    fn truncate_ctx(&mut self, at: usize, ctx: &Self::Ctx) -> Self;
69
70    /// The inverse of truncate. This method mutably truncates an item, keeping all content from
71    /// at..item.len() and returning the item range from 0..at.
72    #[inline(always)]
73    fn truncate_keeping_right_ctx(&mut self, at: usize, ctx: &Self::Ctx) -> Self {
74        let mut other = self.clone();
75        *self = other.truncate_ctx(at, ctx);
76        other
77    }
78
79    fn split_ctx(mut self, at: usize, ctx: &Self::Ctx) -> (Self, Self) {
80        let remainder = self.truncate_ctx(at, ctx);
81        (self, remainder)
82    }
83}
84
85// Do not implement this directly.
86pub trait SplitableSpan: SplitableSpanCtx<Ctx=()> {
87    /// Split the entry, returning the part of the entry which was jettisoned. After truncating at
88    /// `pos`, self.len() == `pos` and the returned value contains the rest of the items.
89    ///
90    /// ```ignore
91    /// let initial_len = entry.len();
92    /// let rest = entry.truncate(truncate_at);
93    /// assert!(initial_len == truncate_at + rest.len());
94    /// ```
95    ///
96    /// `at` parameter must strictly obey *0 < at < entry.len()*
97    fn truncate(&mut self, at: usize) -> Self {
98        self.truncate_ctx(at, &())
99    }
100
101    /// The inverse of truncate. This method mutably truncates an item, keeping all content from
102    /// at..item.len() and returning the item range from 0..at.
103    #[inline(always)]
104    fn truncate_keeping_right(&mut self, at: usize) -> Self {
105        self.truncate_keeping_right_ctx(at, &())
106    }
107
108    fn split_h(mut self, at: usize) -> (Self, Self) {
109        let remainder = self.truncate_ctx(at, &());
110        (self, remainder)
111    }
112}
113
114impl<T: SplitableSpanCtx<Ctx=()>> SplitableSpan for T {}
115
116// This is a bit of a hack. This wrapper trait lets us use regular splitablespan methods in lots of
117// situations.
118#[derive(Debug)]
119pub struct WithCtx<'a, T: SplitableSpanCtx + Clone>(pub T, pub &'a T::Ctx);
120
121impl<'a, T: SplitableSpanCtx + Clone> Deref for WithCtx<'a, T> {
122    type Target = T;
123
124    fn deref(&self) -> &Self::Target {
125        &self.0
126    }
127}
128
129impl<'a, T: SplitableSpanCtx + Clone> DerefMut for WithCtx<'a, T> {
130    fn deref_mut(&mut self) -> &mut Self::Target {
131        &mut self.0
132    }
133}
134
135impl<'a, T: SplitableSpanCtx + Clone> WithCtx<'a, T> {
136    pub fn new(t: T, ctx: &'a T::Ctx) -> Self {
137        Self(t, ctx)
138    }
139
140    pub fn to_inner(self) -> T {
141        self.0
142    }
143}
144
145impl<'a, T: SplitableSpanCtx + Clone> Clone for WithCtx<'a, T> {
146    fn clone(&self) -> Self {
147        WithCtx(self.0.clone(), self.1)
148    }
149}
150
151impl<'a, T: SplitableSpanCtx> SplitableSpanCtx for WithCtx<'a, T> {
152    type Ctx = ();
153
154    fn truncate_ctx(&mut self, at: usize, _ctx: &Self::Ctx) -> Self {
155        WithCtx(self.0.truncate_ctx(at, self.1), self.1)
156    }
157
158    fn truncate_keeping_right_ctx(&mut self, at: usize, _ctx: &Self::Ctx) -> Self {
159        WithCtx(self.0.truncate_keeping_right_ctx(at, self.1), self.1)
160    }
161}
162
163impl<'a, T: SplitableSpanCtx + HasLength> HasLength for WithCtx<'a, T> {
164    fn len(&self) -> usize {
165        self.0.len()
166    }
167}
168
169// struct WithoutCtx<T: SplitableSpanCtx<Ctx=()>>(T);
170
171
172// impl<T: SplitableSpanCtx<Ctx=()>> SplitableSpan for T {
173//     fn truncate(&mut self, at: usize) -> Self {
174//         self.truncate_ctx(at, &())
175//     }
176//
177//     fn truncate_keeping_right(&mut self, at: usize) -> Self {
178//         self.truncate_keeping_right_ctx(at, &())
179//     }
180//
181//     fn split(self, at: usize) -> (Self, Self) {
182//         self.split_ctx(at, &())
183//     }
184// }
185
186pub trait TrimCtx: SplitableSpanCtx + HasLength {
187    /// Trim self to at most `at` items. Remainder (if any) is returned.
188    #[inline]
189    fn trim_ctx(&mut self, at: usize, ctx: &Self::Ctx) -> Option<Self> {
190        if at >= self.len() {
191            None
192        } else {
193            Some(self.truncate_ctx(at, ctx))
194        }
195    }
196}
197
198impl<T: SplitableSpanCtx + HasLength> TrimCtx for T {}
199
200pub trait Trim: SplitableSpan + HasLength {
201    #[inline]
202    fn trim(&mut self, at: usize) -> Option<Self> {
203        self.trim_ctx(at, &())
204    }
205}
206
207impl<T: SplitableSpan + HasLength> Trim for T {}
208
209
210/// TODO: This could almost always be written to just take a T rather than needing Option.
211pub struct Shatter<T>(Option<T>);
212
213impl<T: SplitableSpan + HasLength> Iterator for Shatter<T> {
214    type Item = T;
215
216    fn next(&mut self) -> Option<Self::Item> {
217        let Some(val) = self.0.as_mut() else { return None; };
218
219        if val.len() > 1 {
220            Some(val.truncate_keeping_right(1))
221        } else {
222            self.0.take()
223        }
224    }
225}
226
227/// Iterate over the individual elements of a given item.
228pub fn shatter<T: SplitableSpan + HasLength>(item: T) -> Shatter<T> {
229    Shatter(Some(item))
230}
231
232pub trait MergableSpan: Clone {
233    /// See if the other item can be appended to self. `can_append` will always be called
234    /// immediately before `append`.
235    fn can_append(&self, other: &Self) -> bool;
236
237    /// Merge the passed item into self. Essentially, self = self + other.
238    ///
239    /// The other item *must* be a valid target for merging
240    /// (as per can_append(), above).
241    fn append(&mut self, other: Self);
242
243    /// Append an item at the start of this item. self = other + self.
244    ///
245    /// This item must be a valid append target for other. That is, `other.can_append(self)` must
246    /// be true for this method to be called.
247    #[inline(always)]
248    fn prepend(&mut self, mut other: Self) {
249        other.append(self.clone());
250        *self = other;
251    }
252}
253
254/// An entry is expected to contain multiple items.
255///
256/// A SplitableSpan is a range entry. That is, an entry which contains a compact run of many
257/// entries internally.
258pub trait SplitAndJoinSpan: HasLength + SplitableSpan + MergableSpan {}
259impl<T: HasLength + SplitableSpan + MergableSpan> SplitAndJoinSpan for T {}
260
261pub trait SplitAndJoinSpanCtx: HasLength + SplitableSpanCtx + MergableSpan {}
262impl<T: HasLength + SplitableSpanCtx + MergableSpan> SplitAndJoinSpanCtx for T {}
263
264/// A SplitableSpan wrapper for any single item.
265#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, Default)]
266pub struct Single<T>(pub T);
267
268/// A splitablespan in reverse. This is useful for making lists in descending order.
269#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, Default)]
270pub struct ReverseSpan<S>(pub S);
271
272impl<T> HasLength for Single<T> {
273    fn len(&self) -> usize { 1 }
274}
275impl<T: Clone> SplitableSpanHelpers for Single<T> {
276    // This is a valid impl because truncate can never be called for single items.
277    fn truncate_h(&mut self, _at: usize) -> Self { panic!("Cannot truncate single sized item"); }
278}
279impl<T: Clone> MergableSpan for Single<T> {
280    fn can_append(&self, _other: &Self) -> bool { false }
281    fn append(&mut self, _other: Self) { panic!("Cannot append to single sized item"); }
282}
283
284// impl<T: HasRleKey> HasRleKey for ReverseSpan<T> {
285//     // You might think we need to reverse this or something, but I don't think thats generally true.
286//     fn rle_key(&self) -> usize {
287//         self.0.rle_key()
288//     }
289// }
290impl<S: HasLength> HasLength for ReverseSpan<S> {
291    fn len(&self) -> usize { self.0.len() }
292}
293impl<S: SplitableSpanCtx<Ctx=()>> SplitableSpanHelpers for ReverseSpan<S> {
294    fn truncate_h(&mut self, at: usize) -> Self {
295        ReverseSpan(self.0.truncate_keeping_right(at))
296    }
297    fn truncate_keeping_right_h(&mut self, at: usize) -> Self {
298        ReverseSpan(self.0.truncate(at))
299    }
300}
301impl<S: MergableSpan> MergableSpan for ReverseSpan<S> {
302    fn can_append(&self, other: &Self) -> bool { other.0.can_append(&self.0) }
303    fn append(&mut self, other: Self) { self.0.prepend(other.0); }
304    fn prepend(&mut self, other: Self) { self.0.append(other.0); }
305}
306
307impl<A, B> MergableSpan for (A, B) where A: MergableSpan, B: MergableSpan {
308    fn can_append(&self, other: &Self) -> bool {
309        self.0.can_append(&other.0) && self.1.can_append(&other.1)
310    }
311
312    fn append(&mut self, other: Self) {
313        self.0.append(other.0);
314        self.1.append(other.1);
315    }
316}
317
318impl<A, B> HasLength for (A, B) where A: HasLength {
319    fn len(&self) -> usize {
320        // debug_assert_eq!(self.0.len(), self.1.len());
321        self.0.len()
322    }
323}
324
325impl<A, B> SplitableSpanHelpers for (A, B) where A: SplitableSpan, B: SplitableSpan {
326    fn truncate_h(&mut self, at: usize) -> Self {
327        (self.0.truncate(at), self.1.truncate(at))
328    }
329}
330
331// impl<A, B> SplitableSpanCtx for (A, B) where A: SplitableSpanCtx, B: SplitableSpanCtx, A::Ctx: Sized, B::Ctx: Sized {
332//     type Ctx = (A::Ctx, B::Ctx);
333//
334//     fn truncate_ctx(&mut self, at: usize, ctx: &Self::Ctx) -> Self {
335//         (self.0.truncate_ctx(at, &ctx.0), self.1.truncate_ctx(at, &ctx.1))
336//     }
337// }
338
339
340// impl<T, E> SplitableSpan for Result<T, E> where T: SplitableSpan + Clone, E: Clone {
341//     fn truncate(&mut self, at: usize) -> Self {
342//         match self {
343//             Ok(v) => Result::Ok(v.truncate(at)),
344//             Err(e) => Result::Err(e.clone())
345//         }
346//     }
347// }
348
349impl<T, E> SplitableSpanCtx for Result<T, E> where T: SplitableSpanCtx + Clone, E: Clone {
350    type Ctx = T::Ctx;
351
352    fn truncate_ctx(&mut self, at: usize, ctx: &Self::Ctx) -> Self {
353        match self {
354            Ok(v) => Result::Ok(v.truncate_ctx(at, ctx)),
355            Err(e) => Result::Err(e.clone())
356        }
357    }
358}
359
360impl<T, E> HasLength for Result<T, E> where T: HasLength, Result<T, E>: Clone {
361    fn len(&self) -> usize {
362        match self {
363            Ok(val) => val.len(),
364            Err(_) => 1
365        }
366    }
367}
368
369impl<V> SplitableSpanHelpers for Option<V> where V: SplitableSpan {
370    fn truncate_h(&mut self, at: usize) -> Self {
371        self.as_mut().map(|v| v.truncate(at))
372        // match self {
373        //     None => None,
374        //     Some(v) => Some(v.truncate(at))
375        // }
376    }
377}
378
379// This will implement SplitableSpan for u8, u16, u32, u64, u128, usize
380// impl<T: Add<Output=T> + Sub + Copy + Eq> SplitableSpan for Range<T>
381// where usize: From<<T as Sub>::Output>, T: From<usize>
382// {
383//     fn len(&self) -> usize {
384//         (self.end - self.start).into()
385//     }
386//
387//     fn truncate(&mut self, at: usize) -> Self {
388//         let old_end = self.end;
389//         self.end = self.start + at.into();
390//         Self { start: self.end, end: old_end }
391//     }
392//
393//     fn can_append(&self, other: &Self) -> bool {
394//         self.end == other.start
395//     }
396//
397//     fn append(&mut self, other: Self) {
398//         self.end = other.end;
399//     }
400// }
401
402// Implement me for all numeric types!
403impl HasLength for Range<u32> {
404    fn len(&self) -> usize { (self.end - self.start) as _ }
405}
406// impl HasLength for Range<usize> {
407//     fn len(&self) -> usize { (self.end - self.start) as _ }
408// }
409
410impl SplitableSpanHelpers for Range<u32> {
411    // This is a valid impl because truncate can never be called for single items.
412    fn truncate_h(&mut self, at: usize) -> Self {
413        let old_end = self.end;
414        self.end = self.start + at as u32;
415        Self { start: self.end, end: old_end }
416    }
417}
418impl MergableSpan for Range<u32> {
419    fn can_append(&self, other: &Self) -> bool {
420        self.end == other.start
421    }
422
423    fn append(&mut self, other: Self) {
424        self.end = other.end;
425    }
426}
427
428impl SplitableSpanHelpers for Range<usize> {
429    // This is a valid impl because truncate can never be called for single items.
430    fn truncate_h(&mut self, at: usize) -> Self {
431        let old_end = self.end;
432        self.end = self.start + at;
433        Self { start: self.end, end: old_end }
434    }
435}
436impl MergableSpan for Range<usize> {
437    fn can_append(&self, other: &Self) -> bool {
438        self.end == other.start
439    }
440
441    fn append(&mut self, other: Self) {
442        self.end = other.end;
443    }
444}
445
446/// Simple test helper to verify an implementation of SplitableSpan is valid and meets expected
447/// constraints.
448///
449/// Use this to test splitablespan implementations in tests.
450// #[cfg(test)]
451pub fn test_splitable_methods_valid<E: SplitAndJoinSpan + std::fmt::Debug + Clone + Eq>(entry: E) {
452    test_splitable_methods_valid_ctx(entry, &());
453}
454
455pub fn test_splitable_methods_valid_ctx<E: SplitAndJoinSpanCtx + std::fmt::Debug + Clone + Eq>(entry: E, ctx: &E::Ctx) {
456    assert!(entry.len() >= 2, "Call this with a larger entry");
457    // dbg!(&entry);
458
459    for i in 1..entry.len() {
460        // Split here and make sure we get the expected results.
461        let mut start = entry.clone();
462        let end = start.truncate_ctx(i, ctx);
463        // dbg!(&start, &end);
464
465        assert_eq!(start.len(), i);
466        assert_eq!(end.len(), entry.len() - i);
467
468        // dbg!(&start, &end);
469        assert!(start.can_append(&end));
470
471        let mut merge_append = start.clone();
472
473        // dbg!(&start, &end);
474        merge_append.append(end.clone());
475        // dbg!(&merge_append);
476        assert_eq!(merge_append, entry);
477
478        let mut merge_prepend = end.clone();
479        merge_prepend.prepend(start.clone());
480        assert_eq!(merge_prepend, entry);
481
482        // Split using truncate_keeping_right. We should get the same behaviour.
483        let mut end2 = entry.clone();
484        let start2 = end2.truncate_keeping_right_ctx(i, ctx);
485        assert_eq!(end2, end);
486        assert_eq!(start2, start);
487    }
488}
489
490#[cfg(test)]
491mod test {
492    use crate::vendor::rle::*;
493    use crate::vendor::rle::rlerun::{RleDRun, RleRun};
494
495    #[test]
496    fn test_rle_run() {
497        assert!(!RleRun { val: 10, len: 5 }.can_append(&RleRun { val: 20, len: 5 }));
498        assert!(RleRun { val: 10, len: 5 }.can_append(&RleRun { val: 10, len: 15 }));
499
500        test_splitable_methods_valid(RleRun { val: 12, len: 5 });
501    }
502
503    #[test]
504    fn test_rle_distinct() {
505        assert!(RleDRun::new(0..10, 'x').can_append(&RleDRun::new(10..20, 'x')));
506        assert!(!RleDRun::new(0..10, 'x').can_append(&RleDRun::new(10..20, 'y')));
507        assert!(!RleDRun::new(0..10, 'x').can_append(&RleDRun::new(11..20, 'x')));
508
509        test_splitable_methods_valid(RleDRun::new(0..10, 'x'));
510    }
511
512    #[test]
513    fn splitable_range() {
514        test_splitable_methods_valid(0..10);
515        test_splitable_methods_valid(0u32..10u32);
516    }
517}