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
174/// A mutable leasable buffer implementation.
175///
176/// A leasable buffer can be used to pass a section of a larger mutable buffer
177/// but still get the entire buffer back in a callback.
178#[derive(Debug, PartialEq)]
179pub struct SubSliceMut<'a, T> {
180    internal: &'a mut [T],
181    active_range: Range<usize>,
182}
183
184impl<'a, T> From<&'a mut [T]> for SubSliceMut<'a, T> {
185    fn from(internal: &'a mut [T]) -> Self {
186        let active_range = 0..(internal.len());
187        Self {
188            internal,
189            active_range,
190        }
191    }
192}
193
194/// An immutable leasable buffer implementation.
195///
196/// A leasable buffer can be used to pass a section of a larger mutable buffer
197/// but still get the entire buffer back in a callback.
198#[derive(Debug, PartialEq)]
199pub struct SubSlice<'a, T> {
200    internal: &'a [T],
201    active_range: Range<usize>,
202}
203
204impl<'a, T> From<&'a [T]> for SubSlice<'a, T> {
205    fn from(internal: &'a [T]) -> Self {
206        let active_range = 0..(internal.len());
207        Self {
208            internal,
209            active_range,
210        }
211    }
212}
213
214/// Holder for either a mutable or immutable SubSlice.
215///
216/// In cases where code needs to support either a mutable or immutable SubSlice,
217/// `SubSliceMutImmut` allows the code to store a single type which can
218/// represent either option.
219pub enum SubSliceMutImmut<'a, T> {
220    Immutable(SubSlice<'a, T>),
221    Mutable(SubSliceMut<'a, T>),
222}
223
224impl<'a, T> From<&'a [T]> for SubSliceMutImmut<'a, T> {
225    fn from(value: &'a [T]) -> Self {
226        Self::Immutable(value.into())
227    }
228}
229
230impl<'a, T> From<&'a mut [T]> for SubSliceMutImmut<'a, T> {
231    fn from(value: &'a mut [T]) -> Self {
232        Self::Mutable(value.into())
233    }
234}
235
236impl<'a, T> SubSliceMutImmut<'a, T> {
237    pub fn reset(&mut self) {
238        match *self {
239            SubSliceMutImmut::Immutable(ref mut buf) => buf.reset(),
240            SubSliceMutImmut::Mutable(ref mut buf) => buf.reset(),
241        }
242    }
243
244    /// Returns the length of the currently accessible portion of the
245    /// SubSlice.
246    pub fn len(&self) -> usize {
247        match *self {
248            SubSliceMutImmut::Immutable(ref buf) => buf.len(),
249            SubSliceMutImmut::Mutable(ref buf) => buf.len(),
250        }
251    }
252
253    pub fn slice<R: RangeBounds<usize>>(&mut self, range: R) {
254        match *self {
255            SubSliceMutImmut::Immutable(ref mut buf) => buf.slice(range),
256            SubSliceMutImmut::Mutable(ref mut buf) => buf.slice(range),
257        }
258    }
259
260    pub fn as_ptr(&self) -> *const T {
261        match *self {
262            SubSliceMutImmut::Immutable(ref buf) => buf.as_ptr(),
263            SubSliceMutImmut::Mutable(ref buf) => buf.as_ptr(),
264        }
265    }
266
267    pub fn map_mut(&mut self, f: impl Fn(&mut SubSliceMut<'a, T>)) {
268        match self {
269            SubSliceMutImmut::Immutable(_) => (),
270            SubSliceMutImmut::Mutable(subslice) => f(subslice),
271        }
272    }
273}
274
275impl<T, I> Index<I> for SubSliceMutImmut<'_, T>
276where
277    I: SliceIndex<[T]>,
278{
279    type Output = <I as SliceIndex<[T]>>::Output;
280
281    fn index(&self, idx: I) -> &Self::Output {
282        match *self {
283            SubSliceMutImmut::Immutable(ref buf) => &buf[idx],
284            SubSliceMutImmut::Mutable(ref buf) => &buf[idx],
285        }
286    }
287}
288
289impl<'a, T> SubSliceMut<'a, T> {
290    /// Create a SubSlice from a passed reference to a raw buffer.
291    pub fn new(buffer: &'a mut [T]) -> Self {
292        let len = buffer.len();
293        SubSliceMut {
294            internal: buffer,
295            active_range: 0..len,
296        }
297    }
298
299    /// Retrieve the raw buffer used to create the SubSlice. Consumes the
300    /// SubSlice.
301    pub fn take(self) -> &'a mut [T] {
302        self.internal
303    }
304
305    /// Resets the SubSlice to its full size, making the entire buffer
306    /// accessible again.
307    ///
308    /// This should only be called by layer that created the SubSlice, and not
309    /// layers that were passed a SubSlice. Layers which are using a SubSlice
310    /// should treat the SubSlice as a traditional Rust slice and not consider
311    /// any additional size to the underlying buffer.
312    ///
313    /// Most commonly, this is called once a sliced leasable buffer is returned
314    /// through a callback.
315    pub fn reset(&mut self) {
316        self.active_range = 0..self.internal.len();
317    }
318
319    /// Returns the length of the currently accessible portion of the SubSlice.
320    pub fn len(&self) -> usize {
321        self.as_slice().len()
322    }
323
324    /// Returns a const pointer to the currently accessible portion of the
325    /// SubSlice.
326    pub fn as_ptr(&self) -> *const T {
327        self.as_slice().as_ptr()
328    }
329
330    /// Returns a mutable pointer to the currently accessible portion of the
331    /// SubSlice.
332    pub fn as_mut_ptr(&mut self) -> *mut T {
333        self.as_mut_slice().as_mut_ptr()
334    }
335
336    /// Returns the bounds of the currently accessible `SubSliceMut` window,
337    /// relative to the underlying, internal buffer.
338    ///
339    /// This method can be used to re-construct a `SubSliceMut`, retaining its
340    /// active window, after `take()`ing its internal buffer. This is useful for
341    /// performing nested sub-slicing and interoperability with interfaces that take
342    /// a `&[u8]` buffer with an offset and length.
343    ///
344    /// ## Example
345    ///
346    /// ```
347    /// use kernel::utilities::leasable_buffer::SubSliceMut;
348    /// let mut buffer: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
349    ///
350    /// // Construct a SubSliceMut and activate a window:
351    /// let mut original_subslicemut = SubSliceMut::new(&mut buffer[..]);
352    /// original_subslicemut.slice(3..5);
353    /// assert!(original_subslicemut.as_slice() == &[3, 4]);
354    ///
355    /// // Destruct the SubSliceMut, extracting its underlying buffer, but
356    /// // remembering its active range:
357    /// let remembered_range = original_subslicemut.active_range();
358    /// let extracted_buffer = original_subslicemut.take();
359    /// assert!(remembered_range == (3..5));
360    ///
361    /// // Construct a new SubSliceMut, over the original buffer, with identical
362    /// // bounds:
363    /// let mut reconstructed_subslicemut = SubSliceMut::new(extracted_buffer);
364    /// reconstructed_subslicemut.slice(remembered_range);
365    ///
366    /// // The new, reconstructed SubSliceMut's window is identical to the
367    /// // original one's:
368    /// assert!(reconstructed_subslicemut.as_slice() == &[3, 4]);
369    /// ```
370    pub fn active_range(&self) -> Range<usize> {
371        self.active_range.clone()
372    }
373
374    /// Returns a slice of the currently accessible portion of the
375    /// LeasableBuffer.
376    pub fn as_slice(&self) -> &[T] {
377        &self.internal[self.active_range.clone()]
378    }
379
380    /// Returns a mutable slice of the currently accessible portion of
381    /// the LeasableBuffer.
382    pub fn as_mut_slice(&mut self) -> &mut [T] {
383        &mut self.internal[self.active_range.clone()]
384    }
385
386    /// Returns `true` if the LeasableBuffer is sliced internally.
387    ///
388    /// This is a useful check when switching between code that uses
389    /// LeasableBuffers and code that uses traditional slice-and-length. Since
390    /// slice-and-length _only_ supports using the entire buffer it is not valid
391    /// to try to use a sliced LeasableBuffer.
392    pub fn is_sliced(&self) -> bool {
393        self.internal.len() != self.len()
394    }
395
396    /// Reduces the range of the SubSlice that is accessible.
397    ///
398    /// This should be called whenever a layer wishes to pass only a portion of
399    /// a larger buffer to another layer.
400    ///
401    /// For example, if the application layer has a 1500 byte packet buffer, but
402    /// wishes to send a 250 byte packet, the upper layer should slice the
403    /// SubSlice down to its first 250 bytes before passing it down:
404    ///
405    /// ```rust,ignore
406    /// let buffer = static_init!([u8; 1500], [0; 1500]);
407    /// let s = SubSliceMut::new(buffer);
408    /// s.slice(0..250);
409    /// network.send(s);
410    /// ```
411    pub fn slice<R: RangeBounds<usize>>(&mut self, range: R) {
412        let start = match range.start_bound() {
413            Bound::Included(s) => *s,
414            Bound::Excluded(s) => *s + 1,
415            Bound::Unbounded => 0,
416        };
417
418        let end = match range.end_bound() {
419            Bound::Included(e) => *e + 1,
420            Bound::Excluded(e) => *e,
421            Bound::Unbounded => self.active_range.end - self.active_range.start,
422        };
423
424        let new_start = min(self.active_range.start + start, self.active_range.end);
425        let new_end = min(new_start + (end - start), self.active_range.end);
426
427        self.active_range = Range {
428            start: new_start,
429            end: new_end,
430        };
431    }
432}
433
434impl<T, I> Index<I> for SubSliceMut<'_, T>
435where
436    I: SliceIndex<[T]>,
437{
438    type Output = <I as SliceIndex<[T]>>::Output;
439
440    fn index(&self, idx: I) -> &Self::Output {
441        &self.internal[self.active_range.clone()][idx]
442    }
443}
444
445impl<T, I> IndexMut<I> for SubSliceMut<'_, T>
446where
447    I: SliceIndex<[T]>,
448{
449    fn index_mut(&mut self, idx: I) -> &mut Self::Output {
450        &mut self.internal[self.active_range.clone()][idx]
451    }
452}
453
454impl<'a, T> SubSlice<'a, T> {
455    /// Create a SubSlice from a passed reference to a raw buffer.
456    pub fn new(buffer: &'a [T]) -> Self {
457        let len = buffer.len();
458        SubSlice {
459            internal: buffer,
460            active_range: 0..len,
461        }
462    }
463
464    /// Retrieve the raw buffer used to create the SubSlice. Consumes the
465    /// SubSlice.
466    pub fn take(self) -> &'a [T] {
467        self.internal
468    }
469
470    /// Resets the SubSlice to its full size, making the entire buffer
471    /// accessible again.
472    ///
473    /// This should only be called by layer that created the SubSlice, and not
474    /// layers that were passed a SubSlice. Layers which are using a SubSlice
475    /// should treat the SubSlice as a traditional Rust slice and not consider
476    /// any additional size to the underlying buffer.
477    ///
478    /// Most commonly, this is called once a sliced leasable buffer is returned
479    /// through a callback.
480    pub fn reset(&mut self) {
481        self.active_range = 0..self.internal.len();
482    }
483
484    /// Returns the length of the currently accessible portion of the SubSlice.
485    pub fn len(&self) -> usize {
486        self.as_slice().len()
487    }
488
489    /// Returns a pointer to the currently accessible portion of the SubSlice.
490    pub fn as_ptr(&self) -> *const T {
491        self.as_slice().as_ptr()
492    }
493
494    /// Returns a slice of the currently accessible portion of the
495    /// LeasableBuffer.
496    pub fn as_slice(&self) -> &[T] {
497        &self.internal[self.active_range.clone()]
498    }
499
500    /// Returns `true` if the LeasableBuffer is sliced internally.
501    ///
502    /// This is a useful check when switching between code that uses
503    /// LeasableBuffers and code that uses traditional slice-and-length. Since
504    /// slice-and-length _only_ supports using the entire buffer it is not valid
505    /// to try to use a sliced LeasableBuffer.
506    pub fn is_sliced(&self) -> bool {
507        self.internal.len() != self.len()
508    }
509
510    /// Returns the bounds of the currently accessible `SubSlice` window,
511    /// relative to the underlying, internal buffer.
512    ///
513    /// This method can be used to re-construct a `SubSlice`, retaining its
514    /// active window, after `take()`ing its internal buffer. This is useful for
515    /// performing nested sub-slicing and interoperability with interfaces that take
516    /// a `&[u8]` buffer with an offset and length.
517    ///
518    /// ## Example
519    ///
520    /// ```
521    /// use kernel::utilities::leasable_buffer::SubSlice;
522    /// let mut buffer: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
523    ///
524    /// // Construct a SubSlice and activate a window:
525    /// let mut original_subslicemut = SubSlice::new(&mut buffer[..]);
526    /// original_subslicemut.slice(3..5);
527    /// assert!(original_subslicemut.as_slice() == &[3, 4]);
528    ///
529    /// // Destruct the SubSlice, extracting its underlying buffer, but
530    /// // remembering its active range:
531    /// let remembered_range = original_subslicemut.active_range();
532    /// let extracted_buffer = original_subslicemut.take();
533    /// assert!(remembered_range == (3..5));
534    ///
535    /// // Construct a new SubSlice, over the original buffer, with identical
536    /// // bounds:
537    /// let mut reconstructed_subslicemut = SubSlice::new(extracted_buffer);
538    /// reconstructed_subslicemut.slice(remembered_range);
539    ///
540    /// // The new, reconstructed SubSlice's window is identical to the
541    /// // original one's:
542    /// assert!(reconstructed_subslicemut.as_slice() == &[3, 4]);
543    /// ```
544    pub fn active_range(&self) -> Range<usize> {
545        self.active_range.clone()
546    }
547
548    /// Reduces the range of the SubSlice that is accessible.
549    ///
550    /// This should be called whenever a layer wishes to pass only a portion of
551    /// a larger buffer to another layer.
552    ///
553    /// For example, if the application layer has a 1500 byte packet buffer, but
554    /// wishes to send a 250 byte packet, the upper layer should slice the
555    /// SubSlice down to its first 250 bytes before passing it down:
556    ///
557    /// ```rust,ignore
558    /// let buffer = unsafe {
559    ///    core::slice::from_raw_parts(core::ptr::addr_of!(_ptr_in_flash), 1500)
560    /// };
561    /// let s = SubSlice::new(buffer);
562    /// s.slice(0..250);
563    /// network.send(s);
564    /// ```
565    pub fn slice<R: RangeBounds<usize>>(&mut self, range: R) {
566        let start = match range.start_bound() {
567            Bound::Included(s) => *s,
568            Bound::Excluded(s) => *s + 1,
569            Bound::Unbounded => 0,
570        };
571
572        let end = match range.end_bound() {
573            Bound::Included(e) => *e + 1,
574            Bound::Excluded(e) => *e,
575            Bound::Unbounded => self.active_range.end - self.active_range.start,
576        };
577
578        let new_start = min(self.active_range.start + start, self.active_range.end);
579        let new_end = min(new_start + (end - start), self.active_range.end);
580
581        self.active_range = Range {
582            start: new_start,
583            end: new_end,
584        };
585    }
586}
587
588impl<T, I> Index<I> for SubSlice<'_, T>
589where
590    I: SliceIndex<[T]>,
591{
592    type Output = <I as SliceIndex<[T]>>::Output;
593
594    fn index(&self, idx: I) -> &Self::Output {
595        &self.internal[self.active_range.clone()][idx]
596    }
597}
598
599#[cfg(test)]
600mod test {
601
602    use crate::utilities::leasable_buffer::SubSliceMut;
603    use crate::utilities::leasable_buffer::SubSliceMutImmut;
604
605    #[test]
606    fn subslicemut_create() {
607        let mut b: [u8; 100] = [0; 100];
608        let s = SubSliceMut::new(&mut b);
609        assert_eq!(s.len(), 100);
610    }
611
612    #[test]
613    fn subslicemut_edit_middle() {
614        let mut b: [u8; 10] = [0; 10];
615        let mut s = SubSliceMut::new(&mut b);
616        s.slice(5..10);
617        s[0] = 1;
618        s.reset();
619        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 1, 0, 0, 0, 0]);
620    }
621
622    #[test]
623    fn subslicemut_double_slice() {
624        let mut b: [u8; 10] = [0; 10];
625        let mut s = SubSliceMut::new(&mut b);
626        s.slice(5..10);
627        s.slice(2..5);
628        s[0] = 2;
629        s.reset();
630        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);
631    }
632
633    #[test]
634    fn subslicemut_double_slice_endopen() {
635        let mut b: [u8; 10] = [0; 10];
636        let mut s = SubSliceMut::new(&mut b);
637        s.slice(5..10);
638        s.slice(3..);
639        s[0] = 3;
640        s.reset();
641        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 0, 0, 0, 3, 0]);
642    }
643
644    #[test]
645    fn subslicemut_double_slice_beginningopen1() {
646        let mut b: [u8; 10] = [0; 10];
647        let mut s = SubSliceMut::new(&mut b);
648        s.slice(5..10);
649        s.slice(..3);
650        s[0] = 4;
651        s.reset();
652        assert_eq!(s.as_slice(), [0, 0, 0, 0, 0, 4, 0, 0, 0, 0]);
653    }
654
655    #[test]
656    fn subslicemut_double_slice_beginningopen2() {
657        let mut b: [u8; 10] = [0; 10];
658        let mut s = SubSliceMut::new(&mut b);
659        s.slice(..5);
660        s.slice(..3);
661        s[0] = 5;
662        s.reset();
663        assert_eq!(s.as_slice(), [5, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
664    }
665
666    #[test]
667    fn subslicemut_double_slice_beginningopen3() {
668        let mut b: [u8; 10] = [0; 10];
669        let mut s = SubSliceMut::new(&mut b);
670        s.slice(2..5);
671        s.slice(..3);
672        s[0] = 6;
673        s.reset();
674        assert_eq!(s.as_slice(), [0, 0, 6, 0, 0, 0, 0, 0, 0, 0]);
675    }
676
677    #[test]
678    #[should_panic]
679    fn subslicemut_double_slice_panic1() {
680        let mut b: [u8; 10] = [0; 10];
681        let mut s = SubSliceMut::new(&mut b);
682        s.slice(2..5);
683        s.slice(..3);
684        s[3] = 1;
685    }
686
687    #[test]
688    #[should_panic]
689    fn subslicemut_double_slice_panic2() {
690        let mut b: [u8; 10] = [0; 10];
691        let mut s = SubSliceMut::new(&mut b);
692        s.slice(4..);
693        s.slice(..3);
694        s[3] = 1;
695    }
696
697    #[test]
698    fn subslicemut_slice_nop() {
699        let mut b: [u8; 10] = [0; 10];
700        let mut s = SubSliceMut::new(&mut b);
701        s.slice(0..10);
702        assert!(!s.is_sliced());
703    }
704
705    #[test]
706    fn subslicemut_slice_empty() {
707        let mut b: [u8; 10] = [0; 10];
708        let mut s = SubSliceMut::new(&mut b);
709        s.slice(1..1);
710        assert_eq!(s.len(), 0);
711    }
712
713    #[test]
714    fn subslicemut_slice_down() {
715        let mut b: [u8; 100] = [0; 100];
716        let mut s = SubSliceMut::new(&mut b);
717        s.slice(0..50);
718        assert_eq!(s.len(), 50);
719    }
720
721    #[test]
722    fn subslicemut_slice_up() {
723        let mut b: [u8; 100] = [0; 100];
724        let mut s = SubSliceMut::new(&mut b);
725        s.slice(0..200);
726        assert_eq!(s.len(), 100);
727    }
728
729    #[test]
730    fn subslicemut_slice_up_ptr() {
731        let mut b: [u8; 100] = [0; 100];
732        let mut s = SubSliceMut::new(&mut b);
733        s.slice(0..200);
734        assert_eq!(s.as_slice().len(), 100);
735    }
736
737    #[test]
738    fn subslicemut_slice_outside() {
739        let mut b: [u8; 10] = [0; 10];
740        let mut s = SubSliceMut::new(&mut b);
741        s.slice(20..25);
742        assert_eq!(s.len(), 0);
743    }
744
745    #[test]
746    fn subslicemut_slice_beyond() {
747        let mut b: [u8; 10] = [0; 10];
748        let mut s = SubSliceMut::new(&mut b);
749        s.slice(6..15);
750        assert_eq!(s.len(), 4);
751    }
752
753    fn slice_len1<T>(mut s: SubSliceMutImmut<T>) {
754        s.slice(4..8);
755        s.slice(0..2);
756        assert_eq!(s.len(), 2);
757    }
758
759    fn slice_len2<T>(mut s: SubSliceMutImmut<T>) {
760        s.slice(4..8);
761        s.slice(3..);
762        assert_eq!(s.len(), 1);
763    }
764
765    fn slice_len3<T>(mut s: SubSliceMutImmut<T>) {
766        s.slice(4..8);
767        s.slice(..);
768        assert_eq!(s.len(), 4);
769    }
770
771    fn slice_len4<T>(mut s: SubSliceMutImmut<T>) {
772        s.slice(5..);
773        s.slice(4..);
774        assert_eq!(s.len(), 1);
775    }
776
777    fn slice_len5<T>(mut s: SubSliceMutImmut<T>) {
778        s.slice(5..);
779        s.slice(5..);
780        assert_eq!(s.len(), 0);
781    }
782
783    #[test]
784    fn subslicemut_slice_len1() {
785        let mut b: [u8; 10] = [0; 10];
786        slice_len1(b.as_mut().into())
787    }
788
789    #[test]
790    fn subslicemut_slice_len2() {
791        let mut b: [u8; 10] = [0; 10];
792        slice_len2(b.as_mut().into())
793    }
794
795    #[test]
796    fn subslicemut_slice_len3() {
797        let mut b: [u8; 10] = [0; 10];
798        slice_len3(b.as_mut().into())
799    }
800
801    #[test]
802    fn subslicemut_slice_len4() {
803        let mut b: [u8; 10] = [0; 10];
804        slice_len4(b.as_mut().into())
805    }
806
807    #[test]
808    fn subslicemut_slice_len5() {
809        let mut b: [u8; 10] = [0; 10];
810        slice_len5(b.as_mut().into())
811    }
812
813    #[test]
814    fn subslice_slice_len1() {
815        let b: [u8; 10] = [0; 10];
816        slice_len1(b.as_ref().into())
817    }
818
819    #[test]
820    fn subslice_slice_len2() {
821        let b: [u8; 10] = [0; 10];
822        slice_len2(b.as_ref().into())
823    }
824
825    #[test]
826    fn subslice_slice_len3() {
827        let b: [u8; 10] = [0; 10];
828        slice_len3(b.as_ref().into())
829    }
830
831    #[test]
832    fn subslice_slice_len4() {
833        let b: [u8; 10] = [0; 10];
834        slice_len4(b.as_ref().into())
835    }
836
837    #[test]
838    fn subslice_slice_len5() {
839        let b: [u8; 10] = [0; 10];
840        slice_len5(b.as_ref().into())
841    }
842
843    fn slice_contents1(mut s: SubSliceMutImmut<u8>) {
844        s.slice(4..8);
845        s.slice(0..2);
846        assert_eq!(s[0], 4);
847        assert_eq!(s[1], 5);
848    }
849
850    fn slice_contents2(mut s: SubSliceMutImmut<u8>) {
851        s.slice(2..);
852        s.slice(5..);
853        assert_eq!(s[0], 7);
854        assert_eq!(s[1], 8);
855        assert_eq!(s[2], 9);
856    }
857
858    #[test]
859    fn subslicemut_slice_contents1() {
860        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
861        slice_contents1(b.as_mut().into())
862    }
863
864    #[test]
865    fn subslicemut_slice_contents2() {
866        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
867        slice_contents2(b.as_mut().into())
868    }
869
870    #[test]
871    fn subslice_slice_contents1() {
872        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
873        slice_contents1(b.as_ref().into())
874    }
875
876    #[test]
877    fn subslice_slice_contents2() {
878        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
879        slice_contents2(b.as_ref().into())
880    }
881
882    fn reset_contents(mut s: SubSliceMutImmut<u8>) {
883        s.slice(4..8);
884        s.slice(0..2);
885        s.reset();
886        assert_eq!(s[0], 0);
887        assert_eq!(s[1], 1);
888        assert_eq!(s[2], 2);
889        assert_eq!(s[3], 3);
890        assert_eq!(s[4], 4);
891        assert_eq!(s[5], 5);
892        assert_eq!(s[6], 6);
893        assert_eq!(s[7], 7);
894        assert_eq!(s[8], 8);
895        assert_eq!(s[9], 9);
896    }
897
898    #[test]
899    fn subslicemut_reset_contents() {
900        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
901        reset_contents(b.as_mut().into())
902    }
903
904    #[test]
905    fn subslice_reset_contents() {
906        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
907        reset_contents(b.as_ref().into())
908    }
909
910    fn reset_panic(mut s: SubSliceMutImmut<u8>) -> u8 {
911        s.reset();
912        s[s.len()]
913    }
914
915    #[test]
916    #[should_panic]
917    fn subslicemut_reset_panic() {
918        let mut b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
919        reset_panic(b.as_mut().into());
920    }
921
922    #[test]
923    #[should_panic]
924    fn subslice_reset_panic() {
925        let b: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
926        reset_panic(b.as_ref().into());
927    }
928}