subslice_offset/
lib.rs

1#![doc = include_str!("../README.md")]
2
3
4use std::mem;
5
6pub trait SubsliceOffset {
7    /// Returns the byte offset of an inner slice relative to an enclosing outer slice.
8    ///
9    /// # Examples
10    ///
11    /// ```
12    /// let string = "a\nb\nc";
13    /// let lines: Vec<&str> = string.lines().collect();
14    /// assert_eq!(string.subslice_offset(lines[0]), Some(0)); // &"a"
15    /// assert_eq!(string.subslice_offset(lines[1]), Some(2)); // &"b"
16    /// assert_eq!(string.subslice_offset(lines[2]), Some(4)); // &"c"
17    /// assert_eq!(string.subslice_offset("other!"), None);
18    /// ```
19    fn subslice_offset<'a>(&'a self, inner: &'a Self) -> Option<usize>;
20}
21
22impl SubsliceOffset for str {
23    fn subslice_offset<'a>(&'a self, inner: &'a Self) -> Option<usize> {
24        let outer = self.as_ptr() as usize;
25        let inner = inner.as_ptr() as usize;
26        if inner < outer || inner > outer.wrapping_add(self.len()) {
27            None
28        } else {
29            Some(inner.wrapping_sub(outer))
30        }
31    }
32}
33
34impl<T> SubsliceOffset for [T] {
35    fn subslice_offset<'a>(&'a self, inner: &'a Self) -> Option<usize> {
36        let outer = self.as_ptr_range().start as usize..self.as_ptr_range().end as usize;
37        let inner_start = inner.as_ptr_range().start as usize;
38        if inner_start < outer.start || inner_start > outer.end {
39            None
40        } else {
41            Some(inner_start.wrapping_sub(outer.start) / mem::size_of::<T>())
42        }
43    }
44}