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}