diff --git a/rust/hg-core/src/utils.rs b/rust/hg-core/src/utils.rs --- a/rust/hg-core/src/utils.rs +++ b/rust/hg-core/src/utils.rs @@ -61,6 +61,36 @@ } } +/// Find the offset of the subslice relative to the original collection +/// +/// This function panics for zero-sized types. +/// # Examples: +/// +/// ``` +/// use crate::hg::utils::subslice_offset; +/// let mut line = b"Subslice me!".to_vec(); +/// assert_eq!(subslice_offset(&line, &line[8..]), Some(8)); +/// +/// assert_eq!(subslice_offset(&line, b"hahaha"), None); +/// +/// // Empty array +/// let v: [u8; 0] = []; +/// assert_eq!(subslice_offset(&v, &v), Some(0)); +/// assert_eq!(subslice_offset(&v, b"hehe"), None); +/// ``` +pub fn subslice_offset(outer: &[T], inner: &[T]) -> Option { + let pointee_size = std::mem::size_of::(); + assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize); + + let outer_start = outer.as_ptr() as usize; + let inner = inner.as_ptr() as usize; + if inner < outer_start || inner > outer_start.wrapping_add(outer.len()) { + None + } else { + Some(inner.wrapping_sub(outer_start)) + } +} + pub trait SliceExt { fn trim_end(&self) -> &Self; fn trim_start(&self) -> &Self;