1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use crate::{SharedBytes, SharedStr};
use std::{fmt::Debug, ops::Range};

mod private {
    pub trait Sealed {}
}

pub trait RangeOfSubset: private::Sealed {
    fn range_of_subset(&self, subset: &Self) -> Range<usize>;
}

impl<T> private::Sealed for [T] where T: Debug {}
impl<T> RangeOfSubset for [T]
where
    T: Debug,
{
    fn range_of_subset(&self, subset: &Self) -> Range<usize> {
        self.as_ptr().range_of_subset(subset.as_ptr(), subset.len())
    }
}

impl private::Sealed for str {}
impl RangeOfSubset for str {
    fn range_of_subset(&self, subset: &Self) -> Range<usize> {
        self.as_ptr().range_of_subset(subset.as_ptr(), subset.len())
    }
}

impl private::Sealed for SharedBytes {}
impl RangeOfSubset for SharedBytes {
    fn range_of_subset(&self, subset: &Self) -> Range<usize> {
        self.range_of_subset(subset)
    }
}

impl private::Sealed for SharedStr {}
impl RangeOfSubset for SharedStr {
    fn range_of_subset(&self, subset: &Self) -> Range<usize> {
        self.range_of_subset(subset)
    }
}

trait PtrRangeOfSubset {
    fn range_of_subset(self, subset_ptr: Self, subset_length: usize) -> Range<usize>;

    fn try_range_of_subset(self, subset_ptr: Self, subset_length: usize) -> Option<Range<usize>>;
}

impl<T> PtrRangeOfSubset for *const T
where
    T: Debug,
{
    fn range_of_subset(self, subset_ptr: Self, subset_length: usize) -> Range<usize> {
        self.try_range_of_subset(subset_ptr, subset_length)
            .unwrap_or_else(|| {
                panic!("slice at {subset_ptr:?} is not a subset of slice at {self:?}")
            })
    }

    fn try_range_of_subset(self, subset_ptr: Self, subset_length: usize) -> Option<Range<usize>> {
        let start = (subset_ptr as usize).checked_sub(self as usize)?;
        let end = start.checked_add(subset_length)?;
        Some(start..end)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn shared_bytes_range_of_subset() {
        let bytes = [0, 1, 2, 3, 4];
        let shared = SharedBytes::from(bytes.to_vec());
        let expected = 0..3;
        let actual = shared.range_of_subset(&shared[expected.clone()]);
        assert_eq!(actual, expected);
    }
}