|
11 | 11 | use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
12 | 12 | use crate::marker::Copy;
|
13 | 13 | use crate::mem;
|
14 |
| -use crate::ops::{FnMut, Range, RangeBounds}; |
| 14 | +use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds}; |
15 | 15 | use crate::option::Option;
|
16 | 16 | use crate::option::Option::{None, Some};
|
17 | 17 | use crate::ptr;
|
@@ -75,6 +75,24 @@ pub use index::SliceIndex;
|
75 | 75 | #[unstable(feature = "slice_check_range", issue = "76393")]
|
76 | 76 | pub use index::check_range;
|
77 | 77 |
|
| 78 | +/// Calculates the direction and split point of a one-sided range. |
| 79 | +/// |
| 80 | +/// Helper for `take` and `take_mut` which returns a boolean |
| 81 | +/// indicating whether the front of the split is being taken |
| 82 | +/// (as opposed to the back), as well as a number indicating the |
| 83 | +/// index at which to split. Returns `None` if the split index would |
| 84 | +/// overflow `usize`. |
| 85 | +#[inline] |
| 86 | +fn take_split_point(range: impl OneSidedRange<usize>) -> Option<(bool, usize)> { |
| 87 | + Some(match (range.start_bound(), range.end_bound()) { |
| 88 | + (Bound::Unbounded, Bound::Excluded(i)) => (true, *i), |
| 89 | + (Bound::Unbounded, Bound::Included(i)) => (true, i.checked_add(1)?), |
| 90 | + (Bound::Excluded(i), Bound::Unbounded) => (false, i.checked_add(1)?), |
| 91 | + (Bound::Included(i), Bound::Unbounded) => (false, *i), |
| 92 | + _ => unreachable!(), |
| 93 | + }) |
| 94 | +} |
| 95 | + |
78 | 96 | #[lang = "slice"]
|
79 | 97 | #[cfg(not(test))]
|
80 | 98 | impl<T> [T] {
|
@@ -3059,6 +3077,227 @@ impl<T> [T] {
|
3059 | 3077 |
|
3060 | 3078 | left
|
3061 | 3079 | }
|
| 3080 | + |
| 3081 | + /// Removes and returns the portion of the slice specified by `range`. |
| 3082 | + /// |
| 3083 | + /// If the provided `range` starts or ends outside of the slice, |
| 3084 | + /// `None` is returned and the slice is not modified. |
| 3085 | + /// |
| 3086 | + /// # Examples |
| 3087 | + /// |
| 3088 | + /// Taking the first three items from a slice (via `..3`): |
| 3089 | + /// |
| 3090 | + /// ``` |
| 3091 | + /// #![feature(slice_take)] |
| 3092 | + /// |
| 3093 | + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; |
| 3094 | + /// let mut first_three = slice.take(..3).unwrap(); |
| 3095 | + /// |
| 3096 | + /// assert_eq!(slice, &['d']); |
| 3097 | + /// assert_eq!(first_three, &['a', 'b', 'c']); |
| 3098 | + /// ``` |
| 3099 | + /// |
| 3100 | + /// Taking the tail of a slice starting at index two (via `2..`): |
| 3101 | + /// |
| 3102 | + /// ``` |
| 3103 | + /// #![feature(slice_take)] |
| 3104 | + /// |
| 3105 | + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; |
| 3106 | + /// let mut tail = slice.take(2..).unwrap(); |
| 3107 | + /// |
| 3108 | + /// assert_eq!(slice, &['a', 'b']); |
| 3109 | + /// assert_eq!(tail, &['c', 'd']); |
| 3110 | + /// ``` |
| 3111 | + /// |
| 3112 | + /// Getting `None` when `range` starts or ends outside of the slice: |
| 3113 | + /// |
| 3114 | + /// ``` |
| 3115 | + /// #![feature(slice_take)] |
| 3116 | + /// |
| 3117 | + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; |
| 3118 | + /// |
| 3119 | + /// assert_eq!(None, slice.take(5..)); |
| 3120 | + /// assert_eq!(None, slice.take(..5)); |
| 3121 | + /// assert_eq!(None, slice.take(..=4)); |
| 3122 | + /// let expected: &[char] = &['a', 'b', 'c', 'd']; |
| 3123 | + /// assert_eq!(Some(expected), slice.take(..4)); |
| 3124 | + /// ``` |
| 3125 | + #[inline] |
| 3126 | + #[unstable(feature = "slice_take", issue = "62280")] |
| 3127 | + pub fn take<'a, R: OneSidedRange<usize>>(self: &mut &'a Self, range: R) -> Option<&'a Self> { |
| 3128 | + let (taking_front, split_index) = take_split_point(range)?; |
| 3129 | + if split_index > self.len() { |
| 3130 | + return None; |
| 3131 | + } |
| 3132 | + let original = crate::mem::take(self); |
| 3133 | + let (front, back) = original.split_at(split_index); |
| 3134 | + if taking_front { |
| 3135 | + *self = back; |
| 3136 | + Some(front) |
| 3137 | + } else { |
| 3138 | + *self = front; |
| 3139 | + Some(back) |
| 3140 | + } |
| 3141 | + } |
| 3142 | + |
| 3143 | + /// Removes and returns the portion of the mutable slice specified by `range`. |
| 3144 | + /// |
| 3145 | + /// If the provided `range` starts or ends outside of the slice, |
| 3146 | + /// `None` is returned and the slice is not modified. |
| 3147 | + /// |
| 3148 | + /// # Examples |
| 3149 | + /// |
| 3150 | + /// Taking the first three items from a slice (via `..3`): |
| 3151 | + /// |
| 3152 | + /// ``` |
| 3153 | + /// #![feature(slice_take)] |
| 3154 | + /// |
| 3155 | + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; |
| 3156 | + /// let mut first_three = slice.take_mut(..3).unwrap(); |
| 3157 | + /// |
| 3158 | + /// assert_eq!(slice, &mut ['d']); |
| 3159 | + /// assert_eq!(first_three, &mut ['a', 'b', 'c']); |
| 3160 | + /// ``` |
| 3161 | + /// |
| 3162 | + /// Taking the tail of a slice starting at index two (via `2..`): |
| 3163 | + /// |
| 3164 | + /// ``` |
| 3165 | + /// #![feature(slice_take)] |
| 3166 | + /// |
| 3167 | + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; |
| 3168 | + /// let mut tail = slice.take_mut(2..).unwrap(); |
| 3169 | + /// |
| 3170 | + /// assert_eq!(slice, &mut ['a', 'b']); |
| 3171 | + /// assert_eq!(tail, &mut ['c', 'd']); |
| 3172 | + /// ``` |
| 3173 | + /// |
| 3174 | + /// Getting `None` when `range` starts or ends outside of the slice: |
| 3175 | + /// |
| 3176 | + /// ``` |
| 3177 | + /// #![feature(slice_take)] |
| 3178 | + /// |
| 3179 | + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; |
| 3180 | + /// |
| 3181 | + /// assert_eq!(None, slice.take_mut(5..)); |
| 3182 | + /// assert_eq!(None, slice.take_mut(..5)); |
| 3183 | + /// assert_eq!(None, slice.take_mut(..=4)); |
| 3184 | + /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd']; |
| 3185 | + /// assert_eq!(Some(expected), slice.take_mut(..4)); |
| 3186 | + /// ``` |
| 3187 | + #[inline] |
| 3188 | + #[unstable(feature = "slice_take", issue = "62280")] |
| 3189 | + pub fn take_mut<'a, R: OneSidedRange<usize>>( |
| 3190 | + self: &mut &'a mut Self, |
| 3191 | + range: R, |
| 3192 | + ) -> Option<&'a mut Self> { |
| 3193 | + let (taking_front, split_index) = take_split_point(range)?; |
| 3194 | + if split_index > self.len() { |
| 3195 | + return None; |
| 3196 | + } |
| 3197 | + let original = crate::mem::take(self); |
| 3198 | + let (front, back) = original.split_at_mut(split_index); |
| 3199 | + if taking_front { |
| 3200 | + *self = back; |
| 3201 | + Some(front) |
| 3202 | + } else { |
| 3203 | + *self = front; |
| 3204 | + Some(back) |
| 3205 | + } |
| 3206 | + } |
| 3207 | + |
| 3208 | + /// Takes the first element out of the slice. |
| 3209 | + /// |
| 3210 | + /// Returns a reference pointing to the first element of the old slice. |
| 3211 | + /// |
| 3212 | + /// Returns `None` if the slice is empty. |
| 3213 | + /// |
| 3214 | + /// # Examples |
| 3215 | + /// |
| 3216 | + /// ``` |
| 3217 | + /// #![feature(slice_take)] |
| 3218 | + /// |
| 3219 | + /// let mut slice: &[_] = &['a', 'b', 'c']; |
| 3220 | + /// let first = slice.take_first().unwrap(); |
| 3221 | + /// |
| 3222 | + /// assert_eq!(slice, &['b', 'c']); |
| 3223 | + /// assert_eq!(first, &'a'); |
| 3224 | + /// ``` |
| 3225 | + #[inline] |
| 3226 | + #[unstable(feature = "slice_take", issue = "62280")] |
| 3227 | + pub fn take_first<'a>(self: &mut &'a Self) -> Option<&'a T> { |
| 3228 | + self.take(..=0).map(|res| &res[0]) |
| 3229 | + } |
| 3230 | + |
| 3231 | + /// Takes the first element out of the mutable slice. |
| 3232 | + /// |
| 3233 | + /// Returns a mutable reference pointing to the first element of the old slice. |
| 3234 | + /// |
| 3235 | + /// Returns `None` if the slice is empty. |
| 3236 | + /// |
| 3237 | + /// # Examples |
| 3238 | + /// |
| 3239 | + /// ``` |
| 3240 | + /// #![feature(slice_take)] |
| 3241 | + /// |
| 3242 | + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; |
| 3243 | + /// let first = slice.take_first_mut().unwrap(); |
| 3244 | + /// *first = 'd'; |
| 3245 | + /// |
| 3246 | + /// assert_eq!(slice, &['b', 'c']); |
| 3247 | + /// assert_eq!(first, &'d'); |
| 3248 | + /// ``` |
| 3249 | + #[inline] |
| 3250 | + #[unstable(feature = "slice_take", issue = "62280")] |
| 3251 | + pub fn take_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { |
| 3252 | + self.take_mut(..=0).map(|res| &mut res[0]) |
| 3253 | + } |
| 3254 | + |
| 3255 | + /// Takes the last element out of the slice. |
| 3256 | + /// |
| 3257 | + /// Returns a reference pointing to the last element of the old slice. |
| 3258 | + /// |
| 3259 | + /// Returns `None` if the slice is empty. |
| 3260 | + /// |
| 3261 | + /// # Examples |
| 3262 | + /// |
| 3263 | + /// ``` |
| 3264 | + /// #![feature(slice_take)] |
| 3265 | + /// |
| 3266 | + /// let mut slice: &[_] = &['a', 'b', 'c']; |
| 3267 | + /// let last = slice.take_last().unwrap(); |
| 3268 | + /// |
| 3269 | + /// assert_eq!(slice, &['a', 'b']); |
| 3270 | + /// assert_eq!(last, &'c'); |
| 3271 | + /// ``` |
| 3272 | + #[inline] |
| 3273 | + #[unstable(feature = "slice_take", issue = "62280")] |
| 3274 | + pub fn take_last<'a>(self: &mut &'a Self) -> Option<&'a T> { |
| 3275 | + self.take((self.len() - 1)..).map(|res| &res[0]) |
| 3276 | + } |
| 3277 | + |
| 3278 | + /// Takes the last element out of the mutable slice. |
| 3279 | + /// |
| 3280 | + /// Returns a mutable reference pointing to the last element of the old slice. |
| 3281 | + /// |
| 3282 | + /// Returns `None` if the slice is empty. |
| 3283 | + /// |
| 3284 | + /// # Examples |
| 3285 | + /// |
| 3286 | + /// ``` |
| 3287 | + /// #![feature(slice_take)] |
| 3288 | + /// |
| 3289 | + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; |
| 3290 | + /// let last = slice.take_last_mut().unwrap(); |
| 3291 | + /// *last = 'd'; |
| 3292 | + /// |
| 3293 | + /// assert_eq!(slice, &['a', 'b']); |
| 3294 | + /// assert_eq!(last, &'d'); |
| 3295 | + /// ``` |
| 3296 | + #[inline] |
| 3297 | + #[unstable(feature = "slice_take", issue = "62280")] |
| 3298 | + pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { |
| 3299 | + self.take_mut((self.len() - 1)..).map(|res| &mut res[0]) |
| 3300 | + } |
3062 | 3301 | }
|
3063 | 3302 |
|
3064 | 3303 | #[stable(feature = "rust1", since = "1.0.0")]
|
|
0 commit comments