resize_slice/
lib.rs

1#![deny(missing_docs)]
2
3//! Shrinks slice references
4//!
5//! `ResizeSlice` can be used to adjust the starting offset and length of a slice.
6//!
7//! ## Example
8//!
9//! ```
10//! use resize_slice::ResizeSlice;
11//!
12//! let mut slice: &mut [_] = &mut [1, 2, 3, 4, 5];
13//! slice.resize_from(2);
14//!
15//! assert_eq!(slice, &mut [3, 4, 5]);
16//! ```
17
18extern crate uninitialized;
19
20use std::mem::replace;
21use uninitialized::UNINITIALIZED;
22use std::ptr::write_bytes;
23
24/// Extension trait that allows you to resize mutable slice references
25pub trait ResizeSlice {
26    /// Resizes the slice to `start` offset and `end - start` len
27    ///
28    /// # Panics
29    ///
30    /// Panics on out of bounds resize (`start <= end <= self.len()`)
31    fn resize(&mut self, start: usize, end: usize);
32
33    /// Resize to a new beginning offset
34    ///
35    /// # Panics
36    ///
37    /// Panics if `start > self.len()`
38    fn resize_from(&mut self, start: usize);
39
40    /// Resize to a new length
41    ///
42    /// # Panics
43    ///
44    /// Panics if `end > self.len()`
45    fn resize_to(&mut self, end: usize);
46}
47
48impl<'a, T> ResizeSlice for &'a mut [T] {
49    #[inline]
50    fn resize(&mut self, start: usize, end: usize) {
51        assert!(start <= end && end <= self.len());
52        let mut value = replace(self, &mut []);
53        value = &mut {value}[start..end];
54        replace(self, value);
55    }
56
57    #[inline]
58    fn resize_from(&mut self, start: usize) {
59        let len = self.len();
60        self.resize(start, len);
61    }
62
63    #[inline]
64    fn resize_to(&mut self, end: usize) {
65        self.resize(0, end)
66    }
67}
68
69impl<'a, T> ResizeSlice for &'a [T] {
70    #[inline]
71    fn resize(&mut self, start: usize, end: usize) {
72        *self = &self[start..end];
73    }
74
75    #[inline]
76    fn resize_from(&mut self, start: usize) {
77        *self = &self[start..];
78    }
79
80    #[inline]
81    fn resize_to(&mut self, end: usize) {
82        *self = &self[..end];
83    }
84}
85
86/// Extension methods for vector types
87pub trait VecExt<T> {
88    /// Unsafely resize a vector to the specified size, without initializing the memory.
89    unsafe fn uninitialized_resize(&mut self, new_len: usize);
90
91    /// Unsafely resize a vector to the specified size, zeroing the memory.
92    unsafe fn zeroed_resize(&mut self, new_len: usize);
93}
94
95/// Extension methods for slices
96pub trait SliceExt<T> {
97    /// Copies the less of `self.len()` and `src.len()` from `src` into `self`,
98    /// returning the amount of items copied.
99    fn copy_from(&mut self, src: &[T]) -> usize where T: Copy;
100
101    /// Copies elements to another location within the slice, which may overlap.
102    fn copy_inner(&mut self, src: usize, dst: usize, len: usize) where T: Copy;
103}
104
105impl<T> SliceExt<T> for [T] {
106    #[inline]
107    fn copy_from(&mut self, src: &[T]) -> usize where T: Copy {
108        use std::ptr::copy_nonoverlapping;
109        use std::cmp::min;
110
111        let len = min(self.len(), src.len());
112        unsafe {
113            copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), len);
114        }
115        len
116    }
117
118    #[inline]
119    fn copy_inner(&mut self, src: usize, dst: usize, len: usize) where T: Copy {
120        use std::ptr::copy;
121        assert!(self.len() - len >= src && self.len() - len >= dst);
122
123        unsafe {
124            copy(self.as_ptr().offset(src as isize), self.as_mut_ptr().offset(dst as isize), len);
125        }
126    }
127}
128
129impl<T> VecExt<T> for Vec<T> {
130    #[inline]
131    unsafe fn uninitialized_resize(&mut self, new_len: usize) {
132        let len = self.len();
133        if new_len > len {
134            self.reserve_exact(new_len - len);
135        }
136        self.set_len(new_len);
137    }
138
139    #[inline]
140    unsafe fn zeroed_resize(&mut self, new_len: usize) {
141        self.uninitialized_resize(new_len);
142        if !UNINITIALIZED {
143            write_bytes(self.as_mut_ptr(), 0, new_len);
144        }
145    }
146}
147
148#[cfg(feature = "smallvec")]
149mod smallvec_impl {
150    extern crate smallvec;
151    use self::smallvec::{SmallVec, Array};
152
153    use std::ptr::write_bytes;
154    use uninitialized::UNINITIALIZED;
155    use super::VecExt;
156
157    impl<T: Array> VecExt<T::Item> for SmallVec<T> {
158        #[inline]
159        unsafe fn uninitialized_resize(&mut self, new_len: usize) {
160            let len = self.len();
161            if new_len > len {
162                self.reserve_exact(new_len - len);
163            }
164            self.set_len(new_len);
165        }
166
167        #[inline]
168        unsafe fn zeroed_resize(&mut self, new_len: usize) {
169            self.uninitialized_resize(new_len);
170            if !UNINITIALIZED {
171                write_bytes(self.as_mut_ptr(), 0, new_len);
172            }
173        }
174    }
175}
176
177#[test]
178fn resize() {
179    let mut s: &mut [_] = &mut [1, 2, 3];
180    assert_eq!(s.len(), 3);
181
182    s.resize_from(1);
183    assert_eq!(s.len(), 2);
184
185    s.resize_to(1);
186    assert_eq!(s.len(), 1);
187    assert_eq!(s[0], 2);
188
189    s.resize(1, 1);
190    assert_eq!(s.len(), 0);
191}
192
193#[test]
194#[should_panic]
195fn resize_fail() {
196    let mut s: &mut [_] = &mut [1, 2, 3];
197    s.resize_to(4);
198}