rc_slice2/
lib.rs

1//! # `rc-slice2`
2//!
3//! The rc-slice2 library provides `RcSlice` and `ArcSlice` types representing
4//! slices of array-like data structures contained within `Rc` and `Arc`.
5//! Supports raw arrays, boxed slices, `Vec`, and `SmallVec` (with feature
6//! `smallvec`). Includes limited support for resizing the original array, to
7//! conserve memory.
8//!
9//! The library is fully `no_std`, and has zero `unsafe` blocks. Every function
10//! is now fully tested with examples and thorough documentation.
11//!
12//! # What happened to `rc_slice`?
13//!
14//! `rc-slice2` is the successor to the `rc_slice` crate. Ownership was not
15//! transferred due to supply chain trust concerns. This crate's `0.3.1`
16//! version is fully backwards compatible with `rc_slice 0.3.0`. Version
17//! `0.4.0` includes a minor breaking change, because the method of specifying
18//! generic parameters was changed. However, the behavior of the API is still
19//! backwards compatible.
20//!
21//! # Usage
22//!
23//! ```toml
24//! rc-slice2 = "0.4"
25//! ```
26//!
27//! ```rust
28//!
29//! extern crate alloc;
30//! use rc_slice2::RcSlice;
31//! use alloc::rc::Rc;
32//! use RcSlice as Rcs;
33//!
34//! let buffer: Rc<[u8]> = Rc::new([2, 4, 6, 8, 10]);
35//!
36//! // Supports all kinds of slicing during construction
37//! assert_eq!(*Rcs::new(&buffer, 1..4), [4, 6, 8]);
38//! assert_eq!(*Rcs::new(&buffer, ..), [2, 4, 6, 8, 10]);
39//! assert_eq!(*Rcs::new(&buffer, 0..=2), [2, 4, 6]);
40//! assert_eq!(*Rcs::new(&buffer, 10..), []);
41//!
42//! // Behaves like any other slice.
43//! let mut slice = Rcs::new(&buffer, 1..);
44//! assert_eq!(*slice, [4, 6, 8, 10]);
45//! assert_eq!(slice[2..], [8, 10]);
46//! assert_eq!(slice[1], 6);
47//!
48//! // The slice can shrink, and returns cut-off elements.
49//! assert_eq!(Rcs::advance(&mut slice, 2), Some([4, 6].as_slice()));
50//! assert_eq!(*slice, [8, 10]);
51//! assert_eq!(Rcs::retract(&mut slice, 1), Some([10].as_slice()));
52//! assert_eq!(*slice, [8]);
53//!
54//! // If the original buffer can change size, and there is only one
55//! // strong reference, then the buffer can be shrunk to the slice.
56//! let buffer = Rc::new(vec![12, 14, 16, 18, 20]);
57//! let mut slice = Rcs::new(&buffer, 2..4);
58//! assert_eq!(*slice, [16, 18]);
59//!
60//! // Fails because `buffer` is still alive.
61//! assert_eq!(Rcs::shrink(&mut slice), false);
62//! let weak_buffer = Rc::downgrade(&buffer);
63//! core::mem::drop(buffer);
64//!
65//! // Success; only one strong reference. Original buffer has been shrunk.
66//! assert_eq!(Rcs::shrink(&mut slice), true);
67//! let buffer = Rcs::inner(&slice).clone();
68//! assert_eq!(*buffer, [16, 18]);
69//!
70//! // But weak references were not preserved.
71//! assert_eq!(weak_buffer.upgrade(), None);
72//!
73//! ```
74//!
75//! # License
76//!
77//! rc-slice2 is released under the terms of the Apache License, version 2.0 (see
78//! LICENSE-APACHE) or the MIT license (see LICENSE-MIT), at your option.
79
80#![no_std]
81#![deny(unsafe_code)]
82#![deny(missing_docs)]
83#![deny(missing_debug_implementations)]
84
85extern crate alloc;
86
87mod arc;
88mod rc;
89
90use alloc::{boxed::Box, vec::Vec};
91use core::ops::Range;
92
93pub use arc::ArcSlice;
94pub use rc::RcSlice;
95
96/// Trait implemented by any RcSlice-able container. Currently implemented for
97/// arrays, boxed arrays, and vectors.
98pub trait RcSliceContainer {
99    /// The type of the elements in this container.
100    type Item;
101
102    /// The code to call [`shrink_container_to_range`](RcSliceContainer::shrink_container_to_range) is somewhat expensive. Setting this constant to
103    /// `false` allows the compiler to remove almost all of the [`RcSlice::shrink`]
104    /// implementation.
105    const IS_SHRINKABLE: bool;
106
107    /// Return the total length of the container.
108    fn len(&self) -> usize;
109
110    /// Get an immutable slice of the elements within the specified range.
111    fn get(&self, range: Range<usize>) -> Option<&[Self::Item]>;
112
113    /// Get a mutable slice of the elements within the specified range.
114    fn get_mut(&mut self, range: Range<usize>) -> Option<&mut [Self::Item]>;
115
116    /// Shrink the container to just keep the specified range. Returns the new range if
117    /// the container was completely or partially shrunk, or None if the container wasn't
118    /// modified.
119    ///
120    /// If this returns a range then the new range MUST point the the same elements as
121    /// `keep_range`.
122    ///
123    /// If [`IS_SHRINKABLE`](RcSliceContainer::IS_SHRINKABLE) is false, this function is never called, and implementations
124    /// may panic.
125    ///
126    /// The `RcSlice` implementation checks for the `keep_range.len() == self.len()` case,
127    /// so implementations may omit special handling for it. The return value in that case
128    /// may either be `None` or `Some(keep_range) == Some(0..self.len())`.
129    fn shrink_container_to_range(&mut self, keep_range: Range<usize>) -> Option<Range<usize>>;
130}
131
132impl<T> RcSliceContainer for [T] {
133    type Item = T;
134    const IS_SHRINKABLE: bool = false;
135
136    fn len(&self) -> usize {
137        self.len()
138    }
139
140    fn get(&self, range: Range<usize>) -> Option<&[T]> {
141        Self::get(self, range)
142    }
143
144    fn get_mut(&mut self, range: Range<usize>) -> Option<&mut [T]> {
145        Self::get_mut(self, range)
146    }
147
148    fn shrink_container_to_range(&mut self, _keep_range: Range<usize>) -> Option<Range<usize>> {
149        unimplemented!()
150    }
151}
152
153#[test]
154fn test_slice_container_raw_array() {
155    use alloc::rc::Rc;
156    use RcSlice as Rcs;
157
158    let buffer: Rc<[u8]> = Rc::new([2, 4, 6, 8, 10]);
159
160    assert_eq!(*Rcs::new(&buffer, 1..4), [4, 6, 8]);
161    assert_eq!(*Rcs::new(&buffer, ..), [2, 4, 6, 8, 10]);
162    assert_eq!(*Rcs::new(&buffer, 0..=2), [2, 4, 6]);
163    assert_eq!(*Rcs::new(&buffer, 10..), []);
164}
165
166impl<T> RcSliceContainer for Box<[T]> {
167    type Item = T;
168    const IS_SHRINKABLE: bool = false;
169
170    fn len(&self) -> usize {
171        self.as_ref().len()
172    }
173
174    fn get(&self, range: Range<usize>) -> Option<&[Self::Item]> {
175        self.as_ref().get(range)
176    }
177
178    fn get_mut(&mut self, range: Range<usize>) -> Option<&mut [Self::Item]> {
179        self.as_mut().get_mut(range)
180    }
181
182    fn shrink_container_to_range(&mut self, _keep_range: Range<usize>) -> Option<Range<usize>> {
183        unimplemented!()
184    }
185}
186
187#[test]
188fn test_slice_container_boxed_array() {
189    use alloc::rc::Rc;
190    use RcSlice as Rcs;
191
192    let buffer: Rc<Box<[u8]>> = Rc::new(Box::new([2, 4, 6, 8, 10]));
193
194    assert_eq!(*Rcs::new(&buffer, 1..4), [4, 6, 8]);
195    assert_eq!(*Rcs::new(&buffer, ..), [2, 4, 6, 8, 10]);
196    assert_eq!(*Rcs::new(&buffer, 0..=2), [2, 4, 6]);
197    assert_eq!(*Rcs::new(&buffer, 10..), []);
198}
199
200impl<T> RcSliceContainer for Vec<T> {
201    type Item = T;
202    const IS_SHRINKABLE: bool = true;
203
204    fn len(&self) -> usize {
205        self.len()
206    }
207
208    fn get(&self, range: Range<usize>) -> Option<&[T]> {
209        self.as_slice().get(range)
210    }
211
212    fn get_mut(&mut self, range: Range<usize>) -> Option<&mut [T]> {
213        self.as_mut_slice().get_mut(range)
214    }
215
216    fn shrink_container_to_range(&mut self, keep_range: Range<usize>) -> Option<Range<usize>> {
217        // Avoid iterating over anything past the kept range.
218        self.truncate(keep_range.end);
219
220        let mut cur_index = 0;
221        self.retain(|_| {
222            let ret = keep_range.contains(&cur_index);
223            cur_index += 1;
224            ret
225        });
226        self.shrink_to_fit();
227        Some(0..Self::len(self))
228    }
229}
230
231#[test]
232fn test_slice_container_vec() {
233    use alloc::rc::Rc;
234    use alloc::vec;
235    use RcSlice as Rcs;
236
237    let buffer: Rc<Vec<u8>> = Rc::new(vec![2, 4, 6, 8, 10]);
238
239    assert_eq!(*Rcs::new(&buffer, 1..4), [4, 6, 8]);
240    assert_eq!(*Rcs::new(&buffer, ..), [2, 4, 6, 8, 10]);
241    assert_eq!(*Rcs::new(&buffer, 0..=2), [2, 4, 6]);
242    assert_eq!(*Rcs::new(&buffer, 10..), []);
243
244    let mut slice = Rcs::new(&buffer, 1..4);
245    core::mem::drop(buffer);
246    assert_eq!(Rc::strong_count(RcSlice::inner(&slice)), 1);
247    assert_eq!(*slice, [4, 6, 8]);
248    assert_eq!(**RcSlice::inner(&slice), [2, 4, 6, 8, 10]);
249    assert_eq!(RcSlice::shrink(&mut slice), true);
250    assert_eq!(*slice, [4, 6, 8]);
251    assert_eq!(**RcSlice::inner(&slice), [4, 6, 8]);
252}
253
254#[cfg(feature = "smallvec")]
255impl<T: smallvec::Array> RcSliceContainer for smallvec::SmallVec<T> {
256    type Item = T::Item;
257    const IS_SHRINKABLE: bool = true;
258
259    fn len(&self) -> usize {
260        self.len()
261    }
262
263    fn get(&self, range: Range<usize>) -> Option<&[Self::Item]> {
264        self.as_slice().get(range)
265    }
266
267    fn get_mut(&mut self, range: Range<usize>) -> Option<&mut [Self::Item]> {
268        self.as_mut_slice().get_mut(range)
269    }
270
271    fn shrink_container_to_range(&mut self, keep_range: Range<usize>) -> Option<Range<usize>> {
272        if !self.spilled() {
273            // No point to shrink anything.
274            return None;
275        }
276
277        // Avoid iterating over anything past the kept range.
278        self.truncate(keep_range.end);
279
280        let mut cur_index = 0;
281        self.retain(|_| {
282            let ret = keep_range.contains(&cur_index);
283            cur_index += 1;
284            ret
285        });
286        self.shrink_to_fit();
287        Some(0..Self::len(self))
288    }
289}
290
291// Note: Any other tests for smallvec must have the word "smallvec"
292// in the function name (no underscore). `.build.yml` depends on it.
293#[cfg(feature = "smallvec")]
294#[test]
295fn test_slice_container_smallvec() {
296    use alloc::rc::Rc;
297    use alloc::vec;
298    use smallvec::SmallVec;
299    use RcSlice as Rcs;
300
301    let buffer: Rc<SmallVec<[u8; 4]>> = Rc::new(SmallVec::from_vec(vec![2, 4, 6, 8, 10]));
302
303    assert_eq!(*Rcs::new(&buffer, 1..4), [4, 6, 8]);
304    assert_eq!(*Rcs::new(&buffer, ..), [2, 4, 6, 8, 10]);
305    assert_eq!(*Rcs::new(&buffer, 0..=2), [2, 4, 6]);
306    assert_eq!(*Rcs::new(&buffer, 10..), []);
307
308    let mut slice = Rcs::new(&buffer, 1..4);
309    core::mem::drop(buffer);
310    assert_eq!(Rc::strong_count(RcSlice::inner(&slice)), 1);
311    assert_eq!(*slice, [4, 6, 8]);
312    assert_eq!(RcSlice::inner(&slice).as_ref().as_ref(), [2, 4, 6, 8, 10]);
313    assert_eq!(RcSlice::inner(&slice).spilled(), true);
314
315    assert_eq!(RcSlice::shrink(&mut slice), true);
316
317    assert_eq!(*slice, [4, 6, 8]);
318    assert_eq!(RcSlice::inner(&slice).as_ref().as_ref(), [4, 6, 8]);
319    assert_eq!(RcSlice::inner(&slice).spilled(), false);
320}
321
322/// RcSlice over a byte slice.
323#[deprecated(since = "0.4.0")]
324pub type RcBytes = RcSlice<[u8]>;
325
326/// ArcSlice over a byte slice.
327#[deprecated(since = "0.4.0")]
328pub type ArcBytes = ArcSlice<[u8]>;