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)]
148#[cfg(feature = "rand")]
149mod test {
150    use super::*;
151
152    use rand::{Rand, Rng};
153
154    impl Rand for SliceBias {
155        fn rand<R: Rng>(rng: &mut R) -> Self {
156            fn rand_dir<R: Rng>(rng: &mut R) -> BiasDirection {
157                match rng.gen_range::<u8>(0, 2) {
158                    0 => BiasDirection::Left,
159                    _=> BiasDirection::Right,
160                }
161            }
162
163            SliceBias{
164                start: rand_dir(rng),
165                end: rand_dir(rng),
166            }
167        }
168    }
169
170    #[test]
171    fn doc_comments() {
172        use SliceExt;
173        let word = "niño";
174
175        assert_eq!(word.slice_lossy(0..1000, SliceBias::OUT), word);
176        assert_eq!(word.slice_lossy(10..10000, SliceBias::OUT), "");
177        assert_eq!(word.slice_lossy(0..4, SliceBias::OUT), "niñ");
178        assert_eq!(word.slice_lossy(0..3, SliceBias::OUT), "niñ");
179        assert_eq!(word.slice_lossy(0..2, SliceBias::OUT), "ni");
180
181        assert_eq!(word.slice_lossy(0..10000, SliceBias::IN), word);
182        assert_eq!(word.slice_lossy(10..10000, SliceBias::IN), "");
183        assert_eq!(word.slice_lossy(0..4, SliceBias::IN), "niñ");
184        assert_eq!(word.slice_lossy(0..3, SliceBias::IN), "ni");
185        assert_eq!(word.slice_lossy(0..2, SliceBias::IN), "ni");
186        assert_eq!(word.slice_lossy(3..3, SliceBias::IN), "");
187        assert_eq!(word.slice_lossy(3..4, SliceBias::IN), "");
188        assert_eq!(word.slice_lossy(2..3, SliceBias::IN), "");
189
190        assert_eq!(word.slice_lossy(0..1000, SliceBias::LEFT), word);
191        assert_eq!(word.slice_lossy(10..10000, SliceBias::LEFT), "");
192        assert_eq!(word.slice_lossy(0..4, SliceBias::LEFT), "niñ");
193        assert_eq!(word.slice_lossy(0..3, SliceBias::LEFT), "ni");
194        assert_eq!(word.slice_lossy(0..2, SliceBias::LEFT), "ni");
195        assert_eq!(word.slice_lossy(3..3, SliceBias::LEFT), "");
196        assert_eq!(word.slice_lossy(3..4, SliceBias::LEFT), "ñ");
197        assert_eq!(word.slice_lossy(2..3, SliceBias::LEFT), "");
198
199        assert_eq!(word.slice_lossy(0..1000, SliceBias::RIGHT), word);
200        assert_eq!(word.slice_lossy(10..10000, SliceBias::RIGHT), "");
201        assert_eq!(word.slice_lossy(0..4, SliceBias::RIGHT), "niñ");
202        assert_eq!(word.slice_lossy(0..3, SliceBias::RIGHT), "niñ");
203        assert_eq!(word.slice_lossy(0..2, SliceBias::RIGHT), "ni");
204        assert_eq!(word.slice_lossy(3..3, SliceBias::RIGHT), "");
205        assert_eq!(word.slice_lossy(3..4, SliceBias::RIGHT), "");
206        assert_eq!(word.slice_lossy(2..3, SliceBias::RIGHT), "ñ");
207    }
208
209}