From 079560f6cdcad286df2045084ecd21eac88c8586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20W=C3=BClker?= Date: Wed, 20 Sep 2023 14:45:46 +0200 Subject: [PATCH] sl-std: add SubsliceOffset trait See the relevant documentation on the trait for more info --- sl-std/src/lib.rs | 1 + sl-std/src/slice.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 sl-std/src/slice.rs 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 + } + } +}