Skip to main content

kernel/utilities/
leasable_buffer.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Defines a SubSlice type to implement leasable buffers.
6//!
7//! A leasable buffer decouples maintaining a reference to a buffer from the
8//! presentation of the accessible buffer. This allows layers to operate on
9//! "windows" of the buffer while enabling the original reference (and in effect
10//! the entire buffer) to be passed back in a callback.
11//!
12//! Challenge with Normal Rust Slices
13//! ---------------------------------
14//!
15//! Commonly in Tock we want to partially fill a static buffer with some data,
16//! call an asynchronous operation on that data, and then retrieve that buffer
17//! via a callback. In common Rust code, that might look something like this
18//! (for this example we are transmitting data using I2C).
19//!
20//! ```rust,ignore
21//! // Statically declare the buffer. Make sure it is long enough to handle all
22//! // I2C operations we need to perform.
23//! let buffer = static_init!([u8; 64], [0; 64]);
24//!
25//! // Populate the buffer with our current operation.
26//! buffer[0] = OPERATION_SET;
27//! buffer[1] = REGISTER;
28//! buffer[2] = 0x7; // Value to set the register to.
29//!
30//! // Call the I2C hardware to transmit the data, passing the slice we actually
31//! // want to transmit and not the full buffer.
32//! i2c.write(buffer[0..3]);
33//! ```
34//!
35//! The issue with this is that within the I2C driver, `buffer` is now only
36//! three bytes long. When the I2C driver issues the callback to return the
37//! buffer after the transmission completes, the returned buffer will have a
38//! length of three. Effectively, the full static buffer is lost.
39//!
40//! To avoid this, in Tock we always call operations with both the buffer and a
41//! separate length. We now have two lengths, the provided `length` parameter
42//! which is the size of the buffer actually in use, and `buffer.len()` which is
43//! the full size of the static memory.
44//!
45//! ```rust,ignore
46//! // Call the I2C hardware with a reference to the full buffer and the length
47//! // of that buffer it should actually consider.
48//! i2c.write(buffer, 3);
49//! ```
50//!
51//! Now the I2C driver has a reference to the full buffer, and so when it
52//! returns the buffer via callback the client will have access to the full
53//! static buffer.
54//!
55//! Challenge with Buffers + Length
56//! -------------------------------
57//!
58//! Using a reference to the buffer and a separate length parameter is
59//! sufficient to address the challenge of needing variable size buffers when
60//! using static buffers and complying with Rust's memory management. However,
61//! it still has two drawbacks.
62//!
63//! First, all code in Tock that operates on buffers must correctly handle the
64//! separate buffer and length values as though the `buffer` is a `*u8` pointer
65//! (as in more traditional C code). We lose many of the benefits of the higher
66//! level slice primitive in Rust. For example, calling `buffer.len()` when
67//! using data from the buffer is essentially meaningless, as the correct length
68//! is the `length` parameter. When copying data _to_ the buffer, however, not
69//! overflowing the buffer is critical, and using `buffer.len()` _is_ correct.
70//! With separate reference and length managing this is left to the programmer.
71//!
72//! Second, using only a reference and length assumes that the contents of the
73//! buffer will always start at the first entry in the buffer (i.e.,
74//! `buffer[0]`). To support more generic use of the buffer, we might want to
75//! pass a reference, length, _and offset_, so that we can use arbitrary regions
76//! of the buffer, while again retaining a reference to the original buffer to
77//! use in callbacks.
78//!
79//! For example, in networking code it is common to parse headers and then pass
80//! the payload to upper layers. With slices, that might look something like:
81//!
82//! ```rust,ignore
83//! // Check for a valid header of size 10.
84//! if (valid_header(buffer)) {
85//!     self.client.payload_callback(buffer[10..]);
86//! }
87//! ```
88//!
89//! The issue is that again the client loses access to the beginning of the
90//! buffer and that memory is lost.
91//!
92//! We might also want to do this when calling lower-layer operations to avoid
93//! moving and copying data around. Consider a networking layer that needs to
94//! add a header, we might want to do something like:
95//!
96//! ```rust,ignore
97//! buffer[11] = PAYLOAD;
98//! network_layer_send(buffer, 11, 1);
99//!
100//! fn network_layer_send(buffer: &'static [u8], offset: usize, length: usize) {
101//!     buffer[0..11] = header;
102//!     lower_layer_send(buffer);
103//! }
104//! ```
105//!
106//! Now we have to keep track of two parameters which are both redundant with
107//! the API provided by Rust slices.
108//!
109//! Leasable Buffers
110//! ----------------
111//!
112//! A leasable buffer is a data structure that addresses these challenges.
113//! Simply, it provides the Rust slice API while internally always retaining a
114//! reference to the full underlying buffer. To narrow a buffer, the leasable
115//! buffer can be "sliced". To retrieve the full original memory, a leasable
116//! buffer can be "reset".
117//!
118//! A leasable buffer can be sliced multiple times. For example, as a buffer is
119//! parsed in a networking stack, each layer can call slice on the leasable
120//! buffer to remove that layer's header before passing the buffer to the upper
121//! layer.
122//!
123//! Supporting Mutable and Immutable Buffers
124//! ----------------------------------------
125//!
126//! One challenge with implementing leasable buffers in rust is preserving the
127//! mutability of the underlying buffer. If a mutable buffer is passed as an
128//! immutable slice, the mutability of that buffer is "lost" (i.e., when passed
129//! back in a callback the buffer will be immutable). To address this, we must
130//! implement two versions of a leasable buffer: mutable and immutable. That way
131//! a mutable buffer remains mutable.
132//!
133//! Since in Tock most buffers are mutable, the mutable version is commonly
134//! used. However, in cases where size is a concern, immutable buffers from
135//! flash storage may be preferable. In those cases the immutable version may
136//! be used.
137//!
138//! Usage
139//! -----
140//!
141//! `slice()` is used to set the portion of the `SubSlice` that is accessible.
142//! `reset()` makes the entire `SubSlice` accessible again. Typically, `slice()`
143//! will be called prior to passing the buffer down to lower layers, and
144//! `reset()` will be called once the `SubSlice` is returned via a callback.
145//!
146//! ```rust
147//! # use kernel::utilities::leasable_buffer::SubSlice;
148//! let mut internal = ['a', 'b', 'c', 'd'];
149//! let original_base_addr = internal.as_ptr();
150//!
151//! let mut buffer = SubSlice::new(&mut internal);
152//!
153//! buffer.slice(1..3);
154//!
155//! assert_eq!(buffer.as_ptr(), unsafe { original_base_addr.offset(1) });
156//! assert_eq!(buffer.len(), 2);
157//! assert_eq!((buffer[0], buffer[1]), ('b', 'c'));
158//!
159//! buffer.reset();
160//!
161//! assert_eq!(buffer.as_ptr(), original_base_addr);
162//! assert_eq!(buffer.len(), 4);
163//! assert_eq!((buffer[0], buffer[1]), ('a', 'b'));
164//!
165//!  ```
166
167// Author: Amit Levy
168
169use core::cmp::min;
170use core::ops::{Bound, Range, RangeBounds};
171use core::ops::{Index, IndexMut};
172use core::slice::SliceIndex;
173
174use super::copy_range::CopyRange;
175
176/// A mutable leasable buffer implementation.
177///
178/// A leasable buffer can be used to pass a section of a larger mutable buffer
179/// but still get the entire buffer back in a callback.
180#[derive(Debug, PartialEq)]
181pub struct SubSliceMut<'a, T> {
182    internal: &'a mut [T],
183    active_range: Range<usize>,
184}
185
186impl<'a, T> From<&'a mut [T]> for SubSliceMut<'a, T> {
187    fn from(internal: &'a mut [T]) -> Self {
188        let active_range = 0..(internal.len());
189        Self {
190            internal,
191            active_range,
192        }
193    }
194}
195
196/// An immutable leasable buffer implementation.
197///
198/// A leasable buffer can be used to pass a section of a larger mutable buffer
199/// but still get the entire buffer back in a callback.
200#[derive(Debug, PartialEq, Eq)]
201pub struct SubSlice<'a, T> {
202    pub(crate) internal: &'a [T],
203    pub(crate) active_range: CopyRange<usize>,
204}
205
206// Rust's derive fail to automatically infer that `SubSlice` can be
207// `Clone` even if `T: !Clone`.
208impl<T> Clone for SubSlice<'_, T> {
209    fn clone(&self) -> Self {
210        *self
211    }
212}
213
214// Rust's derive fail to automatically infer that `SubSlice` can be
215// `Copy` even if `T: !Copy`.
216impl<T> Copy for SubSlice<'_, T> {}
217
218impl<'a, T> From<&'a [T]> for SubSlice<'a, T> {
219    fn from(internal: &'a [T]) -> Self {
220        let active_range = 0..(internal.len());
221        Self {
222            internal,
223            active_range: active_range.into(),
224        }
225    }
226}
227
228/// Holder for either a mutable or immutable SubSlice.
229///
230/// In cases where code needs to support either a mutable or immutable SubSlice,
231/// `SubSliceMutImmut` allows the code to store a single type which can
232/// represent either option.
233#[derive(Debug)]
234pub enum SubSliceMutImmut<'a, T> {
235    Immutable(SubSlice<'a, T>),
236    Mutable(SubSliceMut<'a, T>),
237}
238
239impl<'a, T> From<&'a [T]> for SubSliceMutImmut<'a, T> {
240    fn from(value: &'a [T]) -> Self {
241        Self::Immutable(value.into())
242    }
243}
244
245impl<'a, T> From<&'a mut [T]> for SubSliceMutImmut<'a, T> {
246    fn from(value: &'a mut [T]) -> Self {
247        Self::Mutable(value.into())
248    }
249}
250
251impl<'a, T> SubSliceMutImmut<'a, T> {
252    pub fn reset(&mut self) {
253        match *self {
254            SubSliceMutImmut::Immutable(ref mut buf) => buf.reset(),
255            SubSliceMutImmut::Mutable(ref mut buf) => buf.reset(),
256        }
257    }
258
259    /// Returns the length of the currently accessible portion of the
260    /// SubSlice.
261    pub fn len(&self) -> usize {
262        match *self {
263            SubSliceMutImmut::Immutable(ref buf) => buf.len(),
264            SubSliceMutImmut::Mutable(ref buf) => buf.len(),
265        }
266    }
267
268    pub fn slice<R: RangeBounds<usize>>(&mut self, range: R) {
269        match *self {
270            SubSliceMutImmut::Immutable(ref mut buf) => buf.slice(range),
271            SubSliceMutImmut::Mutable(ref mut buf) => buf.slice(range),
272        }
273    }
274
275    pub fn as_ptr(&self) -> *const T {
276        match *self {
277            SubSliceMutImmut::Immutable(ref buf) => buf.as_ptr(),
278            SubSliceMutImmut::Mutable(ref buf) => buf.as_ptr(),
279        }
280    }
281
282    pub fn map_mut(&mut self, f: impl Fn(&mut SubSliceMut<'a, T>)) {
283        match self {
284            SubSliceMutImmut::Immutable(_) => (),
285            SubSliceMutImmut::Mutable(subslice) => f(subslice),
286        }
287    }
288}
289
290impl<T, I> Index<I> for SubSliceMutImmut<'_, T>
291where
292    I: SliceIndex<[T]>,
293{
294    type Output = <I as SliceIndex<[T]>>::Output;
295
296    fn index(&self, idx: I) -> &Self::Output {
297        match *self {
298            SubSliceMutImmut::Immutable(ref buf) => &buf[idx],
299            SubSliceMutImmut::Mutable(ref buf) => &buf[idx],
300        }
301    }
302}
303
304impl<'a, T> SubSliceMut<'a, T> {
305    /// Create a SubSlice from a passed reference to a raw buffer.
306    pub fn new(buffer: &'a mut [T]) -> Self {
307        let len = buffer.len();
308        SubSliceMut {
309            internal: buffer,
310            active_range: 0..len,
311        }
312    }
313
314    /// Retrieve the raw buffer used to create the SubSlice. Consumes the
315    /// SubSlice.
316    pub fn take(self) -> &'a mut [T] {
317        self.internal
318    }
319
320    /// Resets the SubSlice to its full size, making the entire buffer
321    /// accessible again.
322    ///
323    /// This should only be called by layer that created the SubSlice, and not
324    /// layers that were passed a SubSlice. Layers which are using a SubSlice
325    /// should treat the SubSlice as a traditional Rust slice and not consider
326    /// any additional size to the underlying buffer.
327    ///
328    /// Most commonly, this is called once a sliced leasable buffer is returned
329    /// through a callback.
330    pub fn reset(&mut self) {
331        self.active_range = 0..self.internal.len();
332    }
333
334    /// Returns the length of the currently accessible portion of the SubSlice.
335    pub fn len(&self) -> usize {
336        self.as_slice().len()
337    }
338
339    /// Returns a const pointer to the currently accessible portion of the
340    /// SubSlice.
341    pub fn as_ptr(&self) -> *const T {
342        self.as_slice().as_ptr()
343    }
344
345    /// Returns a mutable pointer to the currently accessible portion of the
346    /// SubSlice.
347    pub fn as_mut_ptr(&mut self) -> *mut T {
348        self.as_mut_slice().as_mut_ptr()
349    }
350
351    /// Returns the bounds of the currently accessible `SubSliceMut` window,
352    /// relative to the underlying, internal buffer.
353    ///
354    /// This method can be used to re-construct a `SubSliceMut`, retaining its
355    /// active window, after `take()`ing its internal buffer. This is useful for
356    /// performing nested sub-slicing and interoperability with interfaces that take
357    /// a `&[u8]` buffer with an offset and length.
358    ///
359    /// ## Example
360    ///
361    /// ```
362    /// use kernel::utilities::leasable_buffer::SubSliceMut;
363    /// let mut buffer: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
364    ///
365    /// // Construct a SubSliceMut and activate a window:
366    /// let mut original_subslicemut = SubSliceMut::new(&mut buffer[..]);
367    /// original_subslicemut.slice(3..5);
368    /// assert!(original_subslicemut.as_slice() == &[3, 4]);
369    ///
370    /// // Destruct the SubSliceMut, extracting its underlying buffer, but
371    /// // remembering its active range:
372    /// let remembered_range = original_subslicemut.active_range();
373    /// let extracted_buffer = original_subslicemut.take();
374    /// assert!(remembered_range == (3..5));
375    ///
376    /// // Construct a new SubSliceMut, over the original buffer, with identical
377    /// // bounds:
378    /// let mut reconstructed_subslicemut = SubSliceMut::new(extracted_buffer);
379    /// reconstructed_subslicemut.slice(remembered_range);
380    ///
381    /// // The new, reconstructed SubSliceMut's window is identical to the
382    /// // original one's:
383    /// assert!(reconstructed_subslicemut.as_slice() == &[3, 4]);
384    /// ```
385    pub fn active_range(&self) -> Range<usize> {
386        self.active_range.clone()
387    }
388
389    /// Returns a slice of the currently accessible portion of the
390    /// LeasableBuffer.
391    pub fn as_slice(&self) -> &[T] {
392        &self.internal[self.active_range.clone()]
393    }
394
395    /// Returns a mutable slice of the currently accessible portion of
396    /// the LeasableBuffer.
397    pub fn as_mut_slice(&mut self) -> &mut [T] {
398        &mut self.internal[self.active_range.clone()]
399    }
400
401    /// Returns `true` if the LeasableBuffer is sliced internally.
402    ///
403    /// This is a useful check when switching between code that uses
404    /// LeasableBuffers and code that uses traditional slice-and-length. Since
405    /// slice-and-length _only_ supports using the entire buffer it is not valid
406    /// to try to use a sliced LeasableBuffer.
407    pub fn is_sliced(&self) -> bool {
408        self.internal.len() != self.len()
409    }
410
411    /// Reduces the range of the SubSlice that is accessible.
412    ///
413    /// This should be called whenever a layer wishes to pass only a portion of
414    /// a larger buffer to another layer.
415    ///
416    /// For example, if the application layer has a 1500 byte packet buffer, but
417    /// wishes to send a 250 byte packet, the upper layer should slice the
418    /// SubSlice down to its first 250 bytes before passing it down:
419    ///
420    /// ```rust,ignore
421    /// let buffer = static_init!([u8; 1500], [0; 1500]);
422    /// let s = SubSliceMut::new(buffer);
423    /// s.slice(0..250);
424    /// network.send(s);
425    /// ```
426    pub fn slice<R: RangeBounds<usize>>(&mut self, range: R) {
427        let start = match range.start_bound() {
428            Bound::Included(s) => *s,
429            Bound::Excluded(s) => *s + 1,
430            Bound::Unbounded => 0,
431        };
432
433        let end = match range.end_bound() {
434            Bound::Included(e) => *e + 1,
435            Bound::Excluded(e) => *e,
436            Bound::Unbounded => self.active_range.end - self.active_range.start,
437        };
438
439        let new_start = min(self.active_range.start + start, self.active_range.end);
440        let new_end = min(new_start + (end - start), self.active_range.end);
441
442        self.active_range = Range {
443            start: new_start,
444            end: new_end,
445        };
446    }
447}
448
449impl<T, I> Index<I> for SubSliceMut<'_, T>
450where
451    I: SliceIndex<[T]>,
452{
453    type Output = <I as SliceIndex<[T]>>::Output;
454
455    fn index(&self, idx: I) -> &Self::Output {
456        &self.internal[self.active_range.clone()][idx]
457    }
458}
459
460impl<T, I> IndexMut<I> for SubSliceMut<'_, T>
461where
462    I: SliceIndex<[T]>,
463{
464    fn index_mut(&mut self, idx: I) -> &mut Self::Output {
465        &mut self.internal[self.active_range.clone()][idx]
466    }
467}
468
469impl<'a, T> SubSlice<'a, T> {
470    /// Create a SubSlice from a passed reference to a raw buffer.
471    pub fn new(buffer: &'a [T]) -> Self {
472        let len = buffer.len();
473        SubSlice {
474            internal: buffer,
475            active_range: (0..len).into(),
476        }
477    }
478
479    /// Retrieve the raw buffer used to create the SubSlice. Consumes the
480    /// SubSlice.
481    pub fn take(self) -> &'a [T] {
482        self.internal
483    }
484
485    /// Resets the SubSlice to its full size, making the entire buffer
486    /// accessible again.
487    ///
488    /// This should only be called by layer that created the SubSlice, and not
489    /// layers that were passed a SubSlice. Layers which are using a SubSlice
490    /// should treat the SubSlice as a traditional Rust slice and not consider
491    /// any additional size to the underlying buffer.
492    ///
493    /// Most commonly, this is called once a sliced leasable buffer is returned
494    /// through a callback.
495    pub fn reset(&mut self) {
496        self.active_range = (0..self.internal.len()).into();
497    }
498
499    /// Returns the length of the currently accessible portion of the SubSlice.
500    pub fn len(&self) -> usize {
501        self.as_slice().len()
502    }
503
504    /// Returns a pointer to the currently accessible portion of the SubSlice.
505    pub fn as_ptr(&self) -> *const T {
506        self.as_slice().as_ptr()
507    }
508
509    /// Returns a slice of the currently accessible portion of the
510    /// LeasableBuffer.
511    pub fn as_slice(&self) -> &[T] {
512        &self.internal[Range::from(self.active_range)]
513    }
514
515    /// Returns `true` if the LeasableBuffer is sliced internally.
516    ///
517    /// This is a useful check when switching between code that uses
518    /// LeasableBuffers and code that uses traditional slice-and-length. Since
519    /// slice-and-length _only_ supports using the entire buffer it is not valid
520    /// to try to use a sliced LeasableBuffer.
521    pub fn is_sliced(&self) -> bool {
522        self.internal.len() != self.len()
523    }
524
525    /// Returns the bounds of the currently accessible `SubSlice` window,
526    /// relative to the underlying, internal buffer.
527    ///
528    /// This method can be used to re-construct a `SubSlice`, retaining its
529    /// active window, after `take()`ing its internal buffer. This is useful for
530    /// performing nested sub-slicing and interoperability with interfaces that take
531    /// a `&[u8]` buffer with an offset and length.
532    ///
533    /// ## Example
534    ///
535    /// ```
536    /// use kernel::utilities::leasable_buffer::SubSlice;
537    /// let mut buffer: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
538    ///
539    /// // Construct a SubSlice and activate a window:
540    /// let mut original_subslicemut = SubSlice::new(&mut buffer[..]);
541    /// original_subslicemut.slice(3..5);
542    /// assert!(original_subslicemut.as_slice() == &[3, 4]);
543    ///
544    /// // Destruct the SubSlice, extracting its underlying buffer, but
545    /// // remembering its active range:
546    /// let remembered_range = original_subslicemut.active_range();
547    /// let extracted_buffer = original_subslicemut.take();
548    /// assert!(remembered_range == (3..5));
549    ///
550    /// // Construct a new SubSlice, over the original buffer, with identical
551    /// // bounds:
552    /// let mut reconstructed_subslicemut = SubSlice::new(extracted_buffer);
553    /// reconstructed_subslicemut.slice(remembered_range);
554    ///
555    /// // The new, reconstructed SubSlice's window is identical to the
556    /// // original one's:
557    /// assert!(reconstructed_subslicemut.as_slice() == &[3, 4]);
558    /// ```
559    pub fn active_range(&self) -> Range<usize> {
560        self.active_range.into()
561    }
562
563    /// Reduces the range of the SubSlice that is accessible.
564    ///
565    /// This should be called whenever a layer wishes to pass only a portion of
566    /// a larger buffer to another layer.
567    ///
568    /// For example, if the application layer has a 1500 byte packet buffer, but
569    /// wishes to send a 250 byte packet, the upper layer should slice the
570    /// SubSlice down to its first 250 bytes before passing it down:
571    ///
572    /// ```rust,ignore
573    /// let buffer = unsafe {
574    ///    core::slice::from_raw_parts(core::ptr::addr_of!(_ptr_in_flash), 1500)
575    /// };
576    /// let s = SubSlice::new(buffer);
577    /// s.slice(0..250);
578    /// network.send(s);
579    /// ```
580    pub fn slice<R: RangeBounds<usize>>(&mut self, range: R) {
581        let start = match range.start_bound() {
582            Bound::Included(s) => *s,
583            Bound::Excluded(s) => *s + 1,
584            Bound::Unbounded => 0,
585        };
586
587        let end = match range.end_bound() {
588            Bound::Included(e) => *e + 1,
589            Bound::Excluded(e) => *e,
590            Bound::Unbounded => self.active_range.end - self.active_range.start,
591        };
592
593        let new_start = min(self.active_range.start + start, self.active_range.end);
594        let new_end = min(new_start + (end - start), self.active_range.end);
595
596        self.active_range = CopyRange {
597            start: new_start,
598            end: new_end,
599        };
600    }
601}
602
603impl<T, I> Index<I> for SubSlice<'_, T>
604where
605    I: SliceIndex<[T]>,
606{
607    type Output = <I as SliceIndex<[T]>>::Output;
608
609    fn index(&self, idx: I) -> &Self::Output {
610        &self.internal[Range::from(self.active_range)][idx]
611    }
612}
613
614#[cfg(test)]
615mod test {
616
617    use crate::utilities::leasable_buffer::SubSliceMut;
618    use crate::utilities::leasable_buffer::SubSliceMutImmut;
619
620    #[test]
621    fn subslicemut_create() {
622        let mut b: [u8; 100] = [0; 100];
623        let s = SubSliceMut::new(&mut b);
624        assert_eq!(s.len(), 100);
625    }
626
627    #[test]
628    fn subslicemut_edit_middle() {
629        let mut b: [u8; 10] = [0; 10];
630        let mut s = SubSliceMut::new(&mut b);
631        s.slice(5..10);
632        s[0] = 1;
633        s.reset();
634        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 1, 0, 0, 0, 0]);
635    }
636
637    #[test]
638    fn subslicemut_double_slice() {
639        let mut b: [u8; 10] = [0; 10];
640        let mut s = SubSliceMut::new(&mut b);
641        s.slice(5..10);
642        s.slice(2..5);
643        s[0] = 2;
644        s.reset();
645        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);
646    }
647
648    #[test]
649    fn subslicemut_double_slice_endopen() {
650        let mut b: [u8; 10] = [0; 10];
651        let mut s = SubSliceMut::new(&mut b);
652        s.slice(5..10);
653        s.slice(3..);
654        s[0] = 3;
655        s.reset();
656        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 0, 0, 0, 3, 0]);
657    }
658
659    #[test]
660    fn subslicemut_double_slice_beginningopen1() {
661        let mut b: [u8; 10] = [0; 10];
662        let mut s = SubSliceMut::new(&mut b);
663        s.slice(5..10);
664        s.slice(..3);
665        s[0] = 4;
666        s.reset();
667        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 4, 0, 0, 0, 0]);
668    }
669
670    #[test]
671    fn subslicemut_double_slice_beginningopen2() {
672        let mut b: [u8; 10] = [0; 10];
673        let mut s = SubSliceMut::new(&mut b);
674        s.slice(..5);
675        s.slice(..3);
676        s[0] = 5;
677        s.reset();
678        assert_eq!(s.as_slice(), [5, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
679    }
680
681    #[test]
682    fn subslicemut_double_slice_beginningopen3() {
683        let mut b: [u8; 10] = [0; 10];
684        let mut s = SubSliceMut::new(&mut b);
685        s.slice(2..5);
686        s.slice(..3);
687        s[0] = 6;
688        s.reset();
689        assert_eq!(s.as_slice(), [0, 0, 6, 0, 0, 0, 0, 0, 0, 0]);
690    }
691
692    #[test]
693    #[should_panic]
694    fn subslicemut_double_slice_panic1() {
695        let mut b: [u8; 10] = [0; 10];
696        let mut s = SubSliceMut::new(&mut b);
697        s.slice(2..5);
698        s.slice(..3);
699        s[3] = 1;
700    }
701
702    #[test]
703    #[should_panic]
704    fn subslicemut_double_slice_panic2() {
705        let mut b: [u8; 10] = [0; 10];
706        let mut s = SubSliceMut::new(&mut b);
707        s.slice(4..);
708        s.slice(..3);
709        s[3] = 1;
710    }
711
712    #[test]
713    fn subslicemut_slice_nop() {
714        let mut b: [u8; 10] = [0; 10];
715        let mut s = SubSliceMut::new(&mut b);
716        s.slice(0..10);
717        assert!(!s.is_sliced());
718    }
719
720    #[test]
721    fn subslicemut_slice_empty() {
722        let mut b: [u8; 10] = [0; 10];
723        let mut s = SubSliceMut::new(&mut b);
724        s.slice(1..1);
725        assert_eq!(s.len(), 0);
726    }
727
728    #[test]
729    fn subslicemut_slice_down() {
730        let mut b: [u8; 100] = [0; 100];
731        let mut s = SubSliceMut::new(&mut b);
732        s.slice(0..50);
733        assert_eq!(s.len(), 50);
734    }
735
736    #[test]
737    fn subslicemut_slice_up() {
738        let mut b: [u8; 100] = [0; 100];
739        let mut s = SubSliceMut::new(&mut b);
740        s.slice(0..200);
741        assert_eq!(s.len(), 100);
742    }
743
744    #[test]
745    fn subslicemut_slice_up_ptr() {
746        let mut b: [u8; 100] = [0; 100];
747        let mut s = SubSliceMut::new(&mut b);
748        s.slice(0..200);
749        assert_eq!(s.as_slice().len(), 100);
750    }
751
752    #[test]
753    fn subslicemut_slice_outside() {
754        let mut b: [u8; 10] = [0; 10];
755        let mut s = SubSliceMut::new(&mut b);
756        s.slice(20..25);
757        assert_eq!(s.len(), 0);
758    }
759
760    #[test]
761    fn subslicemut_slice_beyond() {
762        let mut b: [u8; 10] = [0; 10];
763        let mut s = SubSliceMut::new(&mut b);
764        s.slice(6..15);
765        assert_eq!(s.len(), 4);
766    }
767
768    fn slice_len1<T>(mut s: SubSliceMutImmut<T>) {
769        s.slice(4..8);
770        s.slice(0..2);
771        assert_eq!(s.len(), 2);
772    }
773
774    fn slice_len2<T>(mut s: SubSliceMutImmut<T>) {
775        s.slice(4..8);
776        s.slice(3..);
777        assert_eq!(s.len(), 1);
778    }
779
780    fn slice_len3<T>(mut s: SubSliceMutImmut<T>) {
781        s.slice(4..8);
782        s.slice(..);
783        assert_eq!(s.len(), 4);
784    }
785
786    fn slice_len4<T>(mut s: SubSliceMutImmut<T>) {
787        s.slice(5..);
788        s.slice(4..);
789        assert_eq!(s.len(), 1);
790    }
791
792    fn slice_len5<T>(mut s: SubSliceMutImmut<T>) {
793        s.slice(5..);
794        s.slice(5..);
795        assert_eq!(s.len(), 0);
796    }
797
798    #[test]
799    fn subslicemut_slice_len1() {
800        let mut b: [u8; 10] = [0; 10];
801        slice_len1(b.as_mut().into())
802    }
803
804    #[test]
805    fn subslicemut_slice_len2() {
806        let mut b: [u8; 10] = [0; 10];
807        slice_len2(b.as_mut().into())
808    }
809
810    #[test]
811    fn subslicemut_slice_len3() {
812        let mut b: [u8; 10] = [0; 10];
813        slice_len3(b.as_mut().into())
814    }
815
816    #[test]
817    fn subslicemut_slice_len4() {
818        let mut b: [u8; 10] = [0; 10];
819        slice_len4(b.as_mut().into())
820    }
821
822    #[test]
823    fn subslicemut_slice_len5() {
824        let mut b: [u8; 10] = [0; 10];
825        slice_len5(b.as_mut().into())
826    }
827
828    #[test]
829    fn subslice_slice_len1() {
830        let b: [u8; 10] = [0; 10];
831        slice_len1(b.as_ref().into())
832    }
833
834    #[test]
835    fn subslice_slice_len2() {
836        let b: [u8; 10] = [0; 10];
837        slice_len2(b.as_ref().into())
838    }
839
840    #[test]
841    fn subslice_slice_len3() {
842        let b: [u8; 10] = [0; 10];
843        slice_len3(b.as_ref().into())
844    }
845
846    #[test]
847    fn subslice_slice_len4() {
848        let b: [u8; 10] = [0; 10];
849        slice_len4(b.as_ref().into())
850    }
851
852    #[test]
853    fn subslice_slice_len5() {
854        let b: [u8; 10] = [0; 10];
855        slice_len5(b.as_ref().into())
856    }
857
858    fn slice_contents1(mut s: SubSliceMutImmut<u8>) {
859        s.slice(4..8);
860        s.slice(0..2);
861        assert_eq!(s[0], 4);
862        assert_eq!(s[1], 5);
863    }
864
865    fn slice_contents2(mut s: SubSliceMutImmut<u8>) {
866        s.slice(2..);
867        s.slice(5..);
868        assert_eq!(s[0], 7);
869        assert_eq!(s[1], 8);
870        assert_eq!(s[2], 9);
871    }
872
873    #[test]
874    fn subslicemut_slice_contents1() {
875        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
876        slice_contents1(b.as_mut().into())
877    }
878
879    #[test]
880    fn subslicemut_slice_contents2() {
881        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
882        slice_contents2(b.as_mut().into())
883    }
884
885    #[test]
886    fn subslice_slice_contents1() {
887        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
888        slice_contents1(b.as_ref().into())
889    }
890
891    #[test]
892    fn subslice_slice_contents2() {
893        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
894        slice_contents2(b.as_ref().into())
895    }
896
897    fn reset_contents(mut s: SubSliceMutImmut<u8>) {
898        s.slice(4..8);
899        s.slice(0..2);
900        s.reset();
901        assert_eq!(s[0], 0);
902        assert_eq!(s[1], 1);
903        assert_eq!(s[2], 2);
904        assert_eq!(s[3], 3);
905        assert_eq!(s[4], 4);
906        assert_eq!(s[5], 5);
907        assert_eq!(s[6], 6);
908        assert_eq!(s[7], 7);
909        assert_eq!(s[8], 8);
910        assert_eq!(s[9], 9);
911    }
912
913    #[test]
914    fn subslicemut_reset_contents() {
915        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
916        reset_contents(b.as_mut().into())
917    }
918
919    #[test]
920    fn subslice_reset_contents() {
921        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
922        reset_contents(b.as_ref().into())
923    }
924
925    fn reset_panic(mut s: SubSliceMutImmut<u8>) -> u8 {
926        s.reset();
927        s[s.len()]
928    }
929
930    #[test]
931    #[should_panic]
932    fn subslicemut_reset_panic() {
933        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
934        reset_panic(b.as_mut().into());
935    }
936
937    #[test]
938    #[should_panic]
939    fn subslice_reset_panic() {
940        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
941        reset_panic(b.as_ref().into());
942    }
943}