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}