core_extensions/slices/
slice_bias.rs

1/// What directions [`SliceExt`]`::{`[`slice_lossy`]`, `[`slice_lossy_mut`]`}` are biased towards.
2///
3/// For `str` this has the effect of going in those directions if
4/// the `start` and/or `end` bound is between char boundaries.
5///
6/// For `[T]` this has no effect and
7/// it is recommended to use `()` as a parameter instead
8/// (`()` is converted to [`SliceBias::OUT`](#associatedconstant.OUT)).
9///
10/// # Example
11/// 
12/// ### String
13/// 
14/// ```
15/// use core_extensions::SliceExt;
16/// use core_extensions::slices::SliceBias;
17///
18/// let word = "niño";
19///
20/// assert_eq!(
21///     word.char_indices().collect::<Vec<_>>(),
22///     &[(0, 'n'), (1, 'i'), (2, 'ñ'), (4, 'o')]
23/// );
24///
25/// assert_eq!(word.slice_lossy(0..1000, ()), word);
26/// assert_eq!(word.slice_lossy(10..10000, ()), "");
27/// assert_eq!(word.slice_lossy(0..4, ()), "niñ");
28/// assert_eq!(word.slice_lossy(0..3, ()), "niñ");
29/// assert_eq!(word.slice_lossy(0..2, ()), "ni");
30/// assert_eq!(word.slice_lossy(3..3, ()), "ñ");
31/// assert_eq!(word.slice_lossy(3..4, ()), "ñ");
32/// assert_eq!(word.slice_lossy(2..3, ()), "ñ");
33///
34/// assert_eq!(word.slice_lossy(0..1000, SliceBias::OUT), word);
35/// assert_eq!(word.slice_lossy(10..10000, SliceBias::OUT), "");
36/// assert_eq!(word.slice_lossy(0..4, SliceBias::OUT), "niñ");
37/// assert_eq!(word.slice_lossy(0..3, SliceBias::OUT), "niñ");
38/// assert_eq!(word.slice_lossy(0..2, SliceBias::OUT), "ni");
39/// assert_eq!(word.slice_lossy(3..3, SliceBias::OUT), "ñ");
40/// assert_eq!(word.slice_lossy(3..4, SliceBias::OUT), "ñ");
41/// assert_eq!(word.slice_lossy(2..3, SliceBias::OUT), "ñ");
42///
43/// assert_eq!(word.slice_lossy(0..10000, SliceBias::IN), word);
44/// assert_eq!(word.slice_lossy(10..10000, SliceBias::IN), "");
45/// assert_eq!(word.slice_lossy(0..4, SliceBias::IN), "niñ");
46/// assert_eq!(word.slice_lossy(0..3, SliceBias::IN), "ni");
47/// assert_eq!(word.slice_lossy(0..2, SliceBias::IN), "ni");
48/// assert_eq!(word.slice_lossy(3..3, SliceBias::IN), "");
49/// assert_eq!(word.slice_lossy(3..4, SliceBias::IN), "");
50/// assert_eq!(word.slice_lossy(2..3, SliceBias::IN), "");
51///
52/// assert_eq!(word.slice_lossy(0..1000, SliceBias::LEFT), word);
53/// assert_eq!(word.slice_lossy(10..10000, SliceBias::LEFT), "");
54/// assert_eq!(word.slice_lossy(0..4, SliceBias::LEFT), "niñ");
55/// assert_eq!(word.slice_lossy(0..3, SliceBias::LEFT), "ni");
56/// assert_eq!(word.slice_lossy(0..2, SliceBias::LEFT), "ni");
57/// assert_eq!(word.slice_lossy(3..3, SliceBias::LEFT), "");
58/// assert_eq!(word.slice_lossy(3..4, SliceBias::LEFT), "ñ");
59/// assert_eq!(word.slice_lossy(2..3, SliceBias::LEFT), "");
60///
61/// assert_eq!(word.slice_lossy(0..1000, SliceBias::RIGHT), word);
62/// assert_eq!(word.slice_lossy(10..10000, SliceBias::RIGHT), "");
63/// assert_eq!(word.slice_lossy(0..4, SliceBias::RIGHT), "niñ");
64/// assert_eq!(word.slice_lossy(0..3, SliceBias::RIGHT), "niñ");
65/// assert_eq!(word.slice_lossy(0..2, SliceBias::RIGHT), "ni");
66/// assert_eq!(word.slice_lossy(3..3, SliceBias::RIGHT), "");
67/// assert_eq!(word.slice_lossy(3..4, SliceBias::RIGHT), "");
68/// assert_eq!(word.slice_lossy(2..3, SliceBias::RIGHT), "ñ");
69///
70///
71/// ```
72///
73/// [`SliceExt`]: ./trait.SliceExt.html
74/// [`slice_lossy`]: ./trait.SliceExt.html#tymethod.slice_lossy
75/// [`slice_lossy_mut`]: ./trait.SliceExt.html#tymethod.slice_lossy_mut
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub struct SliceBias {
78    /// bias of the start bound
79    pub start: BiasDirection,
80    /// bias of the end bound
81    pub end: BiasDirection,
82}
83
84/// The direction a range bound is moved towards to make the bound a valid index.
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub enum BiasDirection {
87    /// Means that the bound is biased to lower indices
88    Left,
89    /// Means that the bound is biased to higher indices
90    Right,
91}
92
93impl SliceBias {
94    /// Biased inwards, start bounds go right, end bounds go left.
95    pub const IN: Self = Self {
96        start: BiasDirection::Right,
97        end: BiasDirection::Left,
98    };
99    /// Biased outwards, start bounds go left, end bounds go right.
100    pub const OUT: Self = Self {
101        start: BiasDirection::Left,
102        end: BiasDirection::Right,
103    };
104    /// Biased leftwards, both bounds go left.
105    pub const LEFT: Self = Self {
106        start: BiasDirection::Left,
107        end: BiasDirection::Left,
108    };
109    /// Biased rightwards. both bounds go right.
110    pub const RIGHT: Self = Self {
111        start: BiasDirection::Right,
112        end: BiasDirection::Right,
113    };
114}
115
116/// Returns a [`SliceBias::OUT`](#associatedconstant.OUT)
117impl From<()> for SliceBias {
118    fn from(_: ()) -> Self {
119        Self::OUT
120    }
121}
122
123impl From<BiasDirection> for SliceBias {
124    fn from(dir: BiasDirection) -> Self {
125        Self {
126            start: dir,
127            end: dir,
128        }
129    }
130}
131
132impl From<(BiasDirection,)> for SliceBias {
133    fn from((dir,): (BiasDirection,)) -> Self {
134        Self {
135            start: dir,
136            end: dir,
137        }
138    }
139}
140
141impl From<(BiasDirection, BiasDirection)> for SliceBias {
142    fn from((start, end): (BiasDirection, BiasDirection)) -> Self {
143        Self { start, end }
144    }
145}
146
147#[cfg(test)]
148mod test {
149    use super::*;
150
151    use rand::{Rand, Rng};
152
153    impl Rand for SliceBias {
154        fn rand<R: Rng>(rng: &mut R) -> Self {
155            fn rand_dir<R: Rng>(rng: &mut R) -> BiasDirection {
156                match rng.gen_range::<u8>(0, 2) {
157                    0 => BiasDirection::Left,
158                    _=> BiasDirection::Right,
159                }
160            }
161
162            SliceBias{
163                start: rand_dir(rng),
164                end: rand_dir(rng),
165            }
166        }
167    }
168
169    #[test]
170    fn doc_comments() {
171        use SliceExt;
172        let word = "niño";
173
174        assert_eq!(word.slice_lossy(0..1000, SliceBias::OUT), word);
175        assert_eq!(word.slice_lossy(10..10000, SliceBias::OUT), "");
176        assert_eq!(word.slice_lossy(0..4, SliceBias::OUT), "niñ");
177        assert_eq!(word.slice_lossy(0..3, SliceBias::OUT), "niñ");
178        assert_eq!(word.slice_lossy(0..2, SliceBias::OUT), "ni");
179
180        assert_eq!(word.slice_lossy(0..10000, SliceBias::IN), word);
181        assert_eq!(word.slice_lossy(10..10000, SliceBias::IN), "");
182        assert_eq!(word.slice_lossy(0..4, SliceBias::IN), "niñ");
183        assert_eq!(word.slice_lossy(0..3, SliceBias::IN), "ni");
184        assert_eq!(word.slice_lossy(0..2, SliceBias::IN), "ni");
185        assert_eq!(word.slice_lossy(3..3, SliceBias::IN), "");
186        assert_eq!(word.slice_lossy(3..4, SliceBias::IN), "");
187        assert_eq!(word.slice_lossy(2..3, SliceBias::IN), "");
188
189        assert_eq!(word.slice_lossy(0..1000, SliceBias::LEFT), word);
190        assert_eq!(word.slice_lossy(10..10000, SliceBias::LEFT), "");
191        assert_eq!(word.slice_lossy(0..4, SliceBias::LEFT), "niñ");
192        assert_eq!(word.slice_lossy(0..3, SliceBias::LEFT), "ni");
193        assert_eq!(word.slice_lossy(0..2, SliceBias::LEFT), "ni");
194        assert_eq!(word.slice_lossy(3..3, SliceBias::LEFT), "");
195        assert_eq!(word.slice_lossy(3..4, SliceBias::LEFT), "ñ");
196        assert_eq!(word.slice_lossy(2..3, SliceBias::LEFT), "");
197
198        assert_eq!(word.slice_lossy(0..1000, SliceBias::RIGHT), word);
199        assert_eq!(word.slice_lossy(10..10000, SliceBias::RIGHT), "");
200        assert_eq!(word.slice_lossy(0..4, SliceBias::RIGHT), "niñ");
201        assert_eq!(word.slice_lossy(0..3, SliceBias::RIGHT), "niñ");
202        assert_eq!(word.slice_lossy(0..2, SliceBias::RIGHT), "ni");
203        assert_eq!(word.slice_lossy(3..3, SliceBias::RIGHT), "");
204        assert_eq!(word.slice_lossy(3..4, SliceBias::RIGHT), "");
205        assert_eq!(word.slice_lossy(2..3, SliceBias::RIGHT), "ñ");
206    }
207
208}