diff --git a/sl-std/src/lib.rs b/sl-std/src/lib.rs index 7267f620..16ec9c42 100644 --- a/sl-std/src/lib.rs +++ b/sl-std/src/lib.rs @@ -16,4 +16,5 @@ pub mod chars; pub mod iter; pub mod punycode; pub mod rand; +pub mod slice; pub mod time; diff --git a/sl-std/src/slice.rs b/sl-std/src/slice.rs new file mode 100644 index 00000000..aba98005 --- /dev/null +++ b/sl-std/src/slice.rs @@ -0,0 +1,27 @@ +pub trait SubsliceOffset { + /// Returns the byte offset of an inner slice relative to an enclosing outer slice. + /// + /// Examples + /// + /// ``` + /// let string = "a\nb\nc"; + /// let lines: Vec<&str> = string.lines().collect(); + /// assert!(string.subslice_offset(lines[0]) == Some(0)); // &"a" + /// assert!(string.subslice_offset(lines[1]) == Some(2)); // &"b" + /// assert!(string.subslice_offset(lines[2]) == Some(4)); // &"c" + /// assert!(string.subslice_offset("other!") == None); + /// ``` + fn subslice_offset(&self, inner: &Self) -> Option; +} + +impl SubsliceOffset for str { + fn subslice_offset(&self, inner: &str) -> Option { + let outer = self.as_ptr() as usize; + let inner = inner.as_ptr() as usize; + if (outer..outer + self.len()).contains(&inner) { + Some(inner.wrapping_sub(outer)) + } else { + None + } + } +}