stylish_stringlike/text/
sliceable.rs

1use std::ops::{Bound, RangeBounds};
2/// Provides function for slicing a text object on byte index (like [`str::get`])
3pub trait Sliceable {
4    /// Slice an underlying text object by bytes.
5    ///
6    /// # Example
7    ///
8    /// ```
9    /// use stylish_stringlike::text::Sliceable;
10    /// let foo = "foobar";
11    /// assert_eq!(foo.get(1..4), foo.slice(1..4));
12    /// ```
13    fn slice<R>(&self, range: R) -> Option<Self>
14    where
15        R: std::ops::RangeBounds<usize> + Clone,
16        Self: Sized;
17}
18
19impl<'a> Sliceable for &'a str {
20    fn slice<R>(&self, range: R) -> Option<Self>
21    where
22        R: RangeBounds<usize> + Clone,
23        Self: Sized,
24    {
25        match (range.start_bound(), range.end_bound()) {
26            (Bound::Unbounded, Bound::Unbounded) => self.get(..),
27            (Bound::Unbounded, Bound::Excluded(e)) => self.get(..*e),
28            (Bound::Unbounded, Bound::Included(e)) => self.get(..=*e),
29            (Bound::Excluded(s), Bound::Unbounded) => self.get((*s + 1)..),
30            (Bound::Excluded(s), Bound::Excluded(e)) => self.get((*s + 1)..*e),
31            (Bound::Excluded(s), Bound::Included(e)) => self.get((*s + 1)..=*e),
32            (Bound::Included(s), Bound::Unbounded) => self.get(*s..),
33            (Bound::Included(s), Bound::Excluded(e)) => self.get(*s..*e),
34            (Bound::Included(s), Bound::Included(e)) => self.get(*s..=*e),
35        }
36    }
37}
38
39impl Sliceable for String {
40    fn slice<R>(&self, range: R) -> Option<Self>
41    where
42        R: RangeBounds<usize> + Clone,
43        Self: Sized,
44    {
45        self.as_str().slice(range).map(String::from)
46    }
47}