value_traits/traits/
slices.rs

1/*
2 * SPDX-FileCopyrightText: 2025 Tommaso Fontana
3 * SPDX-FileCopyrightText: 2025 Sebastiano Vigna
4 * SPDX-FileCopyrightText: 2025 Inria
5 *
6 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7 */
8
9//! Traits for by-value slices.
10//!
11//! By-value slices are analogous to Rust's built-in slices, but they operate
12//! on values rather than references. This allows for more flexibility in how
13//! slices are used and manipulated.
14//!
15//! For example, a by-value slice can be defined functionally, implicitly, or
16//! using a succinct/compressed representation.
17//!
18//! The fundamental trait for by-value slices is [`SliceByValue`], which
19//! specifies the type of the values and the length of the slice. Additional
20//! functionality is provided by the [`SliceByValueGet`], [`SliceByValueSet`],
21//! and [`SliceByValueRepl`] traits, which allow for getting, setting, and
22//! replacing values in the slice, respectively. Note that, contrarily to the
23//! standard slices, replacement can be obtained by a pair of get/set
24//! operations: [`SliceByValueRepl`] is just more efficient.
25//!
26//! The [`SliceByValueSubslice`] trait provides methods for obtaining subslices
27//! given a range of indices, and the [`SliceByValueSubsliceMut`] trait provides
28//! mutable versions of these methods.
29//!
30//! Both traits are a combination of underlying traits that provide more
31//! specific subslicing functionality depending on the type of range used. In
32//! the intended usage, these traits are interesting only for implementors, or
33//! in the case an implementation does not provide the full set of ranges.
34//!
35//! ## Examples
36//!
37//! As a very simple worked-out example, let us a by-value read-only slice of
38//! `usize` using a vector of `u8` as a basic form of compression:
39//!
40//! ```rust
41//! use value_traits::slices::*;
42//!
43//! struct CompSlice<'a>(&'a [u8]);
44//!
45//! impl<'a> SliceByValue for CompSlice<'a> {
46//!     type Value = usize;
47//!     fn len(&self) -> usize {
48//!         self.0.len()
49//!     }
50//! }
51//!
52//! impl<'a> SliceByValueGet for CompSlice<'a> {
53//!     unsafe fn get_value_unchecked(&self, index: usize) -> usize {
54//!         unsafe { self.0.get_value_unchecked(index) as usize }
55//!     }
56//! }
57//!
58//! fn f(slice_by_value: impl SliceByValueGet<Value = usize>, index: usize) -> usize {
59//!     slice_by_value.index_value(index)
60//! }
61//!
62//! fn main() {
63//!     let vec = vec![0_u8, 1, 2, 3];
64//!     let slice_by_value = CompSlice(&vec);
65//!     // Note that we can pass a reference
66//!     assert_eq!(f(&slice_by_value, 0), 0);
67//!     assert_eq!(f(&slice_by_value, 1), 1);
68//!     assert_eq!(f(&slice_by_value, 2), 2);
69//!     assert_eq!(f(&slice_by_value, 3), 3);
70//! }
71//!
72//! ```
73//! In this example, instead, we define functionally a slice containing the
74//! first 100 squares:
75//!
76//! ```rust
77//! use value_traits::slices::*;
78//!
79//! struct Squares();
80//!
81//! impl<'a> SliceByValue for Squares {
82//!     type Value = usize;
83//!     fn len(&self) -> usize {
84//!         100
85//!     }
86//! }
87//!
88//! impl<'a> SliceByValueGet for Squares {
89//!     unsafe fn get_value_unchecked(&self, index: usize) -> usize {
90//!         index * index
91//!     }
92//! }
93//!
94//! fn f(slice_by_value: &impl SliceByValueGet<Value = usize>, index: usize) -> usize {
95//!     slice_by_value.index_value(index)
96//! }
97//!
98//! fn main() {
99//!     let squares = Squares();
100//!     for i in 0..100 {
101//!         assert_eq!(squares.index_value(i), i * i);
102//!     }
103//! }
104//! ```
105
106use core::ops::{
107    Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
108};
109
110use crate::{ImplBound, Ref};
111
112/// Basic by-value slice trait, specifying just the type of the values and the
113/// length of the slice.
114pub trait SliceByValue {
115    /// The type of the values in the slice.
116    type Value;
117    /// See [`slice::len`].
118    fn len(&self) -> usize;
119
120    /// See [`slice::is_empty`].
121    fn is_empty(&self) -> bool {
122        self.len() == 0
123    }
124}
125
126impl<S: SliceByValue + ?Sized> SliceByValue for &S {
127    type Value = S::Value;
128    #[inline]
129    fn len(&self) -> usize {
130        (**self).len()
131    }
132}
133
134impl<S: SliceByValue + ?Sized> SliceByValue for &mut S {
135    type Value = S::Value;
136    #[inline]
137    fn len(&self) -> usize {
138        (**self).len()
139    }
140}
141
142#[inline(always)]
143fn assert_index(index: usize, len: usize) {
144    assert!(
145        index < len,
146        "index out of bounds: the len is {len} but the index is {index}",
147    );
148}
149
150#[inline(always)]
151fn assert_range(range: &impl ComposeRange, len: usize) {
152    assert!(
153        range.is_valid(len),
154        "range {range:?} out of range for slice of length {len}: ",
155    );
156}
157
158/// Read-only by-value slice trait.
159///
160/// The only method that must be implemented is
161/// [`get_value_unchecked`](`SliceByValueGet::get_value_unchecked`).
162pub trait SliceByValueGet: SliceByValue {
163    /// See [the `Index` implementation for slices](slice#impl-Index%3CI%3E-for-%5BT%5D).
164    fn index_value(&self, index: usize) -> Self::Value {
165        assert_index(index, self.len());
166        // SAFETY: index is without bounds
167        unsafe { self.get_value_unchecked(index) }
168    }
169
170    /// See [`slice::get_unchecked`].
171    ///
172    /// For a safe alternative see [`get_value`](SliceByValueGet::get_value)
173    /// or [`index_value`](SliceByValueGet::index_value).
174    ///
175    /// # Safety
176    ///
177    /// The index must be within bounds.
178    unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value;
179
180    /// See [`slice::get`].
181    fn get_value(&self, index: usize) -> Option<Self::Value> {
182        if index < self.len() {
183            // SAFETY: index is without bounds
184            let value = unsafe { self.get_value_unchecked(index) };
185            Some(value)
186        } else {
187            None
188        }
189    }
190}
191
192impl<S: SliceByValueGet + ?Sized> SliceByValueGet for &S {
193    fn get_value(&self, index: usize) -> Option<Self::Value> {
194        (**self).get_value(index)
195    }
196    fn index_value(&self, index: usize) -> Self::Value {
197        (**self).index_value(index)
198    }
199    unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
200        unsafe { (**self).get_value_unchecked(index) }
201    }
202}
203
204impl<S: SliceByValueGet + ?Sized> SliceByValueGet for &mut S {
205    fn get_value(&self, index: usize) -> Option<Self::Value> {
206        (**self).get_value(index)
207    }
208    fn index_value(&self, index: usize) -> Self::Value {
209        (**self).index_value(index)
210    }
211    unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
212        unsafe { (**self).get_value_unchecked(index) }
213    }
214}
215
216/// Mutable by-value slice trait providing setting methods.
217///
218/// The only method that must be implemented is
219/// [`set_value_unchecked`](`SliceByValueSet::set_value_unchecked`).
220///
221/// If you need to set a value and get the previous value, use
222/// [`SliceByValueRepl`] instead.
223pub trait SliceByValueSet: SliceByValue {
224    /// Sets the value at the given index to the given value without doing
225    /// bounds checking.
226    ///
227    /// For a safe alternative see [`set_value`](SliceByValueSet::set_value).
228    ///
229    /// # Safety
230    ///
231    /// The index must be within bounds.
232    unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value);
233
234    /// Sets the value at the given index to the given value.
235    ///
236    /// # Panics
237    ///
238    /// This method will panic is the index is not within bounds.
239    fn set_value(&mut self, index: usize, value: Self::Value) {
240        assert_index(index, self.len());
241        // SAFETY: index is without bounds
242        unsafe {
243            self.set_value_unchecked(index, value);
244        }
245    }
246}
247
248impl<S: SliceByValueSet + ?Sized> SliceByValueSet for &mut S {
249    fn set_value(&mut self, index: usize, value: Self::Value) {
250        (**self).set_value(index, value);
251    }
252    unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
253        (**self).set_value_unchecked(index, value);
254    }
255}
256
257/// Mutable by-value slice trait providing replacement methods.
258///
259/// If you just need to set a value, use [`SliceByValueSet`] instead.
260pub trait SliceByValueRepl: SliceByValue {
261    /// Sets the value at the given index to the given value and
262    /// returns the previous value, without doing bounds checking.
263    ///
264    /// For a safe alternative see [`SliceByValueRepl::replace_value`].
265    ///
266    /// # Safety
267    ///
268    /// The index must be within bounds.
269    unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value;
270
271    /// Sets the value at the given index to the given value and
272    /// returns the previous value.
273    ///
274    /// # Panics
275    ///
276    /// This method will panic is the index is not within bounds.
277    fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
278        assert_index(index, self.len());
279        // SAFETY: index is without bounds
280        unsafe { self.replace_value_unchecked(index, value) }
281    }
282}
283
284impl<S: SliceByValueRepl + ?Sized> SliceByValueRepl for &mut S {
285    fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
286        (**self).replace_value(index, value)
287    }
288    unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value {
289        (**self).replace_value_unchecked(index, value)
290    }
291}
292
293/// A range that can check whether it is within the bounds of a slice, and
294/// intersect itself with another range.
295///
296/// This trait is implemented for the six Rust range types in [`core::ops`],
297/// making it possible to treat them uniformly in implementations, and in
298/// particular in procedural macros.
299pub trait ComposeRange: RangeBounds<usize> + core::fmt::Debug {
300    /// Returns `true` if the range is within the bounds of a slice of given
301    /// length
302    fn is_valid(&self, len: usize) -> bool;
303
304    /// Returns a new range that is the composition of `base` with the range.
305    ///
306    /// The resulting range is guaranteed to be contained in `base` if `self` [is
307    /// valid](ComposeRange::is_valid) for `base.len()`.
308    ///
309    /// ```rust
310    /// use value_traits::slices::ComposeRange;
311    ///
312    /// assert_eq!((2..5).compose(10..20),  12..15);
313    /// assert_eq!((2..=5).compose(10..20), 12..16);
314    /// assert_eq!((..5).compose(10..20),   10..15);
315    /// assert_eq!((..=5).compose(10..20),  10..16);
316    /// assert_eq!((2..).compose(10..20),   12..20);
317    /// assert_eq!((..).compose(10..20),    10..20);
318    /// ```
319    fn compose(&self, base: Range<usize>) -> Range<usize>;
320}
321
322impl ComposeRange for Range<usize> {
323    fn is_valid(&self, len: usize) -> bool {
324        self.start <= len && self.end <= len && self.start <= self.end
325    }
326
327    fn compose(&self, base: Range<usize>) -> Range<usize> {
328        (base.start + self.start)..(base.start + self.end)
329    }
330}
331
332impl ComposeRange for RangeFrom<usize> {
333    fn is_valid(&self, len: usize) -> bool {
334        self.start <= len
335    }
336
337    fn compose(&self, base: Range<usize>) -> Range<usize> {
338        (base.start + self.start)..base.end
339    }
340}
341
342impl ComposeRange for RangeFull {
343    fn is_valid(&self, _len: usize) -> bool {
344        true
345    }
346
347    fn compose(&self, base: Range<usize>) -> Range<usize> {
348        base
349    }
350}
351
352impl ComposeRange for RangeInclusive<usize> {
353    fn is_valid(&self, len: usize) -> bool {
354        *self.start() < len && *self.end() < len && self.start() <= self.end()
355    }
356
357    fn compose(&self, base: Range<usize>) -> Range<usize> {
358        (base.start + self.start())..(base.start + self.end() + 1)
359    }
360}
361
362impl ComposeRange for RangeTo<usize> {
363    fn is_valid(&self, len: usize) -> bool {
364        self.end <= len
365    }
366
367    fn compose(&self, base: Range<usize>) -> Range<usize> {
368        base.start..(base.start + self.end)
369    }
370}
371
372impl ComposeRange for RangeToInclusive<usize> {
373    fn is_valid(&self, len: usize) -> bool {
374        self.end < len
375    }
376
377    fn compose(&self, base: Range<usize>) -> Range<usize> {
378        base.start..(base.start + self.end + 1)
379    }
380}
381
382/// A GAT-like trait specifying the subslice type.
383///
384/// It implicitly restricts the lifetime `'a` used in `SliceByValueRange` to be
385/// `where Self: 'a`. Moreover, it requires [`SliceByValueGet`].
386///
387/// As in other theoretical applications of GATs (Generic Associated Types),
388/// like [lenders](https://crates.io/crates/lender), using a GAT to express the
389/// type of a subslice is problematic because when bounding the type itself in a
390/// `where` clause using Higher-Rank Trait Bounds (HRTBs) the bound must be true
391/// for all lifetimes, including `'static`, resulting in the sliced type having
392/// to be `'static` as well.
393///
394/// This is a result of HRTBs not having a way to express qualifiers (`for<'any
395/// where Self: 'any> Self: Trait`) and effectively making HRTBs only useful
396/// when you want to express a trait constraint on *all* lifetimes, including
397/// `'static` (`for<'all> Self: trait`)
398///
399/// Please see [Sabrina's Blog][1] for more information, and how a trait like
400/// this can be used to solve it by implicitly restricting HRTBs.
401///
402/// [1]:
403///     <https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats>
404pub trait SliceByValueSubsliceGat<'a, __Implicit: ImplBound = Ref<'a, Self>>:
405    SliceByValueGet
406{
407    /// The type of the subslice.
408    type Subslice: 'a + SliceByValueGet<Value = Self::Value> + SliceByValueSubslice;
409}
410
411/// A convenience type representing the type of subslice
412/// of a type implementing [`SliceByValueSubsliceGat`].
413#[allow(type_alias_bounds)] // yeah the type alias bounds are not enforced, but they are useful for documentation
414pub type Subslice<'a, T: SliceByValueSubsliceGat<'a>> =
415    <T as SliceByValueSubsliceGat<'a>>::Subslice;
416
417impl<'a, T: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for &T {
418    type Subslice = T::Subslice;
419}
420
421impl<'a, T: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for &mut T {
422    type Subslice = T::Subslice;
423}
424
425/// A trait implementing subslicing for a specific range parameter.
426///
427/// The user should never see this trait. [`SliceByValueSubslice`] combines all
428/// instances of this trait with `R` equal to the various kind of standard
429/// ranges ([`core::ops::Range`], [`core::ops::RangeFull`], etc.).
430///
431/// The only method that must be implemented is
432/// [`get_subslice_unchecked`](`SliceByValueSubsliceRange::get_subslice_unchecked`).
433pub trait SliceByValueSubsliceRange<R: ComposeRange>: for<'a> SliceByValueSubsliceGat<'a> {
434    /// See [the `Index` implementation for slices](slice#impl-Index%3CI%3E-for-%5BT%5D).
435    fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
436        assert_range(&range, self.len());
437        unsafe {
438            // SAFETY: range is within bounds
439            self.get_subslice_unchecked(range)
440        }
441    }
442
443    /// See [`slice::get_unchecked`].
444    ///
445    /// For a safe alternative see
446    /// [`get_subslice`](SliceByValueSubsliceRange::get_subslice) or
447    /// [`index_subslice`](SliceByValueSubsliceRange::index_subslice).
448    ///
449    /// # Safety
450    ///
451    /// The range must be within bounds.
452    unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self>;
453
454    /// See [`slice::get`].
455    fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
456        if range.is_valid(self.len()) {
457            let subslice = unsafe { self.get_subslice_unchecked(range) };
458            Some(subslice)
459        } else {
460            None
461        }
462    }
463}
464
465impl<R: ComposeRange, S: SliceByValueSubsliceRange<R> + ?Sized> SliceByValueSubsliceRange<R>
466    for &S
467{
468    fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
469        (**self).get_subslice(range)
470    }
471    fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
472        (**self).index_subslice(range)
473    }
474    unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self> {
475        unsafe { (**self).get_subslice_unchecked(range) }
476    }
477}
478impl<R: ComposeRange, S: SliceByValueSubsliceRange<R> + ?Sized> SliceByValueSubsliceRange<R>
479    for &mut S
480{
481    fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
482        (**self).get_subslice(range)
483    }
484    fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
485        (**self).index_subslice(range)
486    }
487    unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self> {
488        unsafe { (**self).get_subslice_unchecked(range) }
489    }
490}
491
492/// A GAT-like trait specifying the mutable subslice type.
493///
494/// See [`SliceByValueSubsliceGat`].
495pub trait SliceByValueSubsliceGatMut<'a, __Implicit = &'a Self>:
496    SliceByValueSet + SliceByValueRepl
497{
498    /// The type of the mutable subslice.
499    type SubsliceMut: 'a
500        + SliceByValueSet<Value = Self::Value>
501        + SliceByValueRepl<Value = Self::Value>
502        + SliceByValueSubsliceGatMut<'a, SubsliceMut = Self::SubsliceMut> // recursion
503        + SliceByValueSubsliceMut;
504}
505
506/// A convenience type representing the type of subslice
507/// of a type implementing [`SliceByValueSubsliceGatMut`].
508#[allow(type_alias_bounds)] // yeah the type alias bounds are not enforced, but they are useful for documentation
509pub type SubsliceMut<'a, T: SliceByValueSubsliceGatMut<'a>> =
510    <T as SliceByValueSubsliceGatMut<'a>>::SubsliceMut;
511
512impl<'a, T: SliceByValueSubsliceGatMut<'a> + ?Sized> SliceByValueSubsliceGatMut<'a> for &mut T {
513    type SubsliceMut = T::SubsliceMut;
514}
515
516/// A trait implementing mutable subslicing for a specific range parameter.
517///
518///  The user should never see this trait. [`SliceByValueSubsliceMut`] combines
519/// all instances of this trait with `R` equal to the various kind of standard
520/// ranges ([`core::ops::Range`], [`core::ops::RangeFull`], etc.).
521///
522/// The only method that must be implemented is
523/// [`get_subslice_unchecked_mut`](`SliceByValueSubsliceRangeMut::get_subslice_unchecked_mut`).
524pub trait SliceByValueSubsliceRangeMut<R: ComposeRange>:
525    for<'a> SliceByValueSubsliceGatMut<'a>
526{
527    /// See [the `Index` implementation for slices](slice#impl-Index%3CI%3E-for-%5BT%5D).
528    fn index_subslice_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
529        assert_range(&range, self.len());
530        unsafe {
531            // SAFETY: range is within bounds
532            self.get_subslice_unchecked_mut(range)
533        }
534    }
535
536    /// See [`slice::get_unchecked`].
537    ///
538    /// For a safe alternative see
539    /// [`get_subslice_mut`](SliceByValueSubsliceRangeMut::get_subslice_mut) or
540    /// [`index_subslice_mut`](SliceByValueSubsliceRangeMut::index_subslice_mut).
541    ///
542    /// # Safety
543    ///
544    /// The range must be within bounds.
545    unsafe fn get_subslice_unchecked_mut(&mut self, range: R) -> SubsliceMut<'_, Self>;
546
547    /// See [`slice::get`].
548    fn get_subslice_mut(&mut self, range: R) -> Option<SubsliceMut<'_, Self>> {
549        if range.is_valid(self.len()) {
550            // SAFETY: range is within bounds
551            let subslice_mut = unsafe { self.get_subslice_unchecked_mut(range) };
552            Some(subslice_mut)
553        } else {
554            None
555        }
556    }
557}
558
559impl<R: ComposeRange, S: SliceByValueSubsliceRangeMut<R> + ?Sized> SliceByValueSubsliceRangeMut<R>
560    for &mut S
561{
562    fn get_subslice_mut(&mut self, range: R) -> Option<SubsliceMut<'_, Self>> {
563        (**self).get_subslice_mut(range)
564    }
565    fn index_subslice_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
566        (**self).index_subslice_mut(range)
567    }
568    unsafe fn get_subslice_unchecked_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
569        (**self).get_subslice_unchecked_mut(range)
570    }
571}
572
573/// A convenience trait combining all instances of [`SliceByValueSubsliceRange`]
574/// with `R` equal to the various kind of standard ranges ([`core::ops::Range`],
575/// [`core::ops::RangeFull`], etc.).
576///
577/// A blanket implementation automatically implements the trait if all necessary
578/// implementations of [`SliceByValueSubsliceRange`] are available.
579///
580/// ## Binding the Subslice Type
581///
582/// To bind the iterator type you need to use higher-rank trait
583/// bounds, as in:
584///
585/// ```rust
586/// use value_traits::slices::*;
587///
588/// fn f<S>(s: S) where
589///    S: SliceByValueSubslice + for<'a> SliceByValueSubsliceGat<'a, Subslice = &'a [u8]>,
590/// {
591///     let _: &[u8] = s.index_subslice(0..10);
592/// }
593/// ```
594///
595/// The bound applies uniformly to all type of ranges.
596///
597/// You can also bind the subslice using traits:
598///
599/// ```rust
600/// use value_traits::slices::*;
601///
602/// fn f<S>(s: S) where
603///    S: SliceByValueSubslice + for<'a> SliceByValueSubsliceGat<'a, Subslice: AsRef<[u8]>>,
604/// {
605///     let _: &[u8] = s.index_subslice(0..10).as_ref();
606/// }
607/// ```
608///
609/// In this case, you can equivalently use the [`Subslice`] type alias, which might
610/// be more concise:
611///
612/// ```rust
613/// use value_traits::slices::*;
614///
615/// fn f<S>(s: S) where
616///    S: SliceByValueSubslice,
617///    for<'a> Subslice<'a, S>: AsRef<[u8]>,
618/// {
619///     let _: &[u8] = s.index_subslice(0..10).as_ref();
620/// }
621/// ```
622pub trait SliceByValueSubslice:
623    SliceByValueSubsliceRange<Range<usize>>
624    + SliceByValueSubsliceRange<RangeFrom<usize>>
625    + SliceByValueSubsliceRange<RangeFull>
626    + SliceByValueSubsliceRange<RangeInclusive<usize>>
627    + SliceByValueSubsliceRange<RangeTo<usize>>
628    + SliceByValueSubsliceRange<RangeToInclusive<usize>>
629{
630}
631
632impl<U> SliceByValueSubslice for U
633where
634    U: SliceByValueSubsliceRange<Range<usize>>,
635    U: SliceByValueSubsliceRange<RangeFrom<usize>>,
636    U: SliceByValueSubsliceRange<RangeFull>,
637    U: SliceByValueSubsliceRange<RangeInclusive<usize>>,
638    U: SliceByValueSubsliceRange<RangeTo<usize>>,
639    U: SliceByValueSubsliceRange<RangeToInclusive<usize>>,
640{
641}
642
643/// A convenience trait combining all instances of
644/// [`SliceByValueSubsliceRangeMut`] with `R` equal to the various kind of
645/// standard ranges ([`core::ops::Range`], [`core::ops::RangeFull`], etc.).
646///
647/// A blanket implementation automatically implements the trait if all necessary
648/// implementations of [`SliceByValueSubsliceMut`] are available.
649///
650/// ## Binding the Subslice Type
651///
652/// To bind the iterator type you need to use higher-rank trait
653/// bounds, as in:
654///
655/// ```rust
656/// use value_traits::slices::*;
657///
658/// fn f<S>(mut s: S) where
659///    S: SliceByValueSubsliceMut + for<'a> SliceByValueSubsliceGatMut<'a, SubsliceMut = &'a mut [u8]>,
660/// {
661///     let _: &mut [u8] = s.index_subslice_mut(0..10);
662/// }
663/// ```
664///
665/// The bound applies uniformly to all type of ranges.
666///
667/// You can also bind the subslice using traits:
668///
669/// ```rust
670/// use value_traits::slices::*;
671///
672/// fn f<S>(mut s: S) where
673///    S: SliceByValueSubsliceMut + for<'a> SliceByValueSubsliceGatMut<'a, SubsliceMut: AsMut<[u8]>>,
674/// {
675///     let _: &mut [u8] = s.index_subslice_mut(0..10).as_mut();
676/// }
677/// ```
678///
679/// In this case, you can equivalently use the [`SubsliceMut`] type alias, which might
680/// be more concise:
681///
682/// ```rust
683/// use value_traits::slices::*;
684///
685/// fn f<S>(mut s: S) where
686///    S: SliceByValueSubsliceMut,
687///    for<'a> SubsliceMut<'a, S>: AsMut<[u8]>,
688/// {
689///     let _: &mut [u8] = s.index_subslice_mut(0..10).as_mut();
690/// }
691/// ```
692pub trait SliceByValueSubsliceMut:
693    SliceByValueSubsliceRangeMut<Range<usize>>
694    + SliceByValueSubsliceRangeMut<RangeFrom<usize>>
695    + SliceByValueSubsliceRangeMut<RangeFull>
696    + SliceByValueSubsliceRangeMut<RangeInclusive<usize>>
697    + SliceByValueSubsliceRangeMut<RangeTo<usize>>
698    + SliceByValueSubsliceRangeMut<RangeToInclusive<usize>>
699{
700}
701
702impl<U> SliceByValueSubsliceMut for U
703where
704    U: SliceByValueSubsliceRangeMut<Range<usize>>,
705    U: SliceByValueSubsliceRangeMut<RangeFrom<usize>>,
706    U: SliceByValueSubsliceRangeMut<RangeFull>,
707    U: SliceByValueSubsliceRangeMut<RangeInclusive<usize>>,
708    U: SliceByValueSubsliceRangeMut<RangeTo<usize>>,
709    U: SliceByValueSubsliceRangeMut<RangeToInclusive<usize>>,
710{
711}
712
713#[cfg(feature = "alloc")]
714mod alloc_impls {
715    use super::*;
716    #[cfg(all(feature = "alloc", not(feature = "std")))]
717    use alloc::boxed::Box;
718
719    impl<S: SliceByValue + ?Sized> SliceByValue for Box<S> {
720        type Value = S::Value;
721        #[inline]
722        fn len(&self) -> usize {
723            (**self).len()
724        }
725    }
726
727    impl<S: SliceByValueGet + ?Sized> SliceByValueGet for Box<S> {
728        fn get_value(&self, index: usize) -> Option<Self::Value> {
729            (**self).get_value(index)
730        }
731        fn index_value(&self, index: usize) -> Self::Value {
732            (**self).index_value(index)
733        }
734        unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
735            unsafe { (**self).get_value_unchecked(index) }
736        }
737    }
738
739    impl<S: SliceByValueSet + ?Sized> SliceByValueSet for Box<S> {
740        fn set_value(&mut self, index: usize, value: Self::Value) {
741            (**self).set_value(index, value);
742        }
743        unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
744            unsafe {
745                (**self).set_value_unchecked(index, value);
746            }
747        }
748    }
749
750    impl<S: SliceByValueRepl + ?Sized> SliceByValueRepl for Box<S> {
751        fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
752            (**self).replace_value(index, value)
753        }
754        unsafe fn replace_value_unchecked(
755            &mut self,
756            index: usize,
757            value: Self::Value,
758        ) -> Self::Value {
759            unsafe { (**self).replace_value_unchecked(index, value) }
760        }
761    }
762
763    impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Box<S> {
764        type Subslice = S::Subslice;
765    }
766    impl<'a, S: SliceByValueSubsliceGatMut<'a> + ?Sized> SliceByValueSubsliceGatMut<'a> for Box<S> {
767        type SubsliceMut = S::SubsliceMut;
768    }
769
770    macro_rules! impl_range_alloc {
771        ($range:ty) => {
772            impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
773                for Box<S>
774            {
775                #[inline]
776                fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
777                    (**self).get_subslice(index)
778                }
779
780                #[inline]
781                fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
782                    (**self).index_subslice(index)
783                }
784
785                #[inline]
786                unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
787                    unsafe { (**self).get_subslice_unchecked(index) }
788                }
789            }
790            impl<S: SliceByValueSubsliceRangeMut<$range> + ?Sized>
791                SliceByValueSubsliceRangeMut<$range> for Box<S>
792            {
793                #[inline]
794                fn get_subslice_mut(&mut self, index: $range) -> Option<SubsliceMut<'_, Self>> {
795                    (**self).get_subslice_mut(index)
796                }
797
798                #[inline]
799                fn index_subslice_mut(&mut self, index: $range) -> SubsliceMut<'_, Self> {
800                    (**self).index_subslice_mut(index)
801                }
802
803                #[inline]
804                unsafe fn get_subslice_unchecked_mut(
805                    &mut self,
806                    index: $range,
807                ) -> SubsliceMut<'_, Self> {
808                    unsafe { (**self).get_subslice_unchecked_mut(index) }
809                }
810            }
811        };
812    }
813
814    impl_range_alloc!(RangeFull);
815    impl_range_alloc!(RangeFrom<usize>);
816    impl_range_alloc!(RangeTo<usize>);
817    impl_range_alloc!(Range<usize>);
818    impl_range_alloc!(RangeInclusive<usize>);
819    impl_range_alloc!(RangeToInclusive<usize>);
820}
821
822#[cfg(feature = "std")]
823mod std_impls {
824    use super::*;
825    use std::{rc::Rc, sync::Arc};
826
827    impl<S: SliceByValue + ?Sized> SliceByValue for Arc<S> {
828        type Value = S::Value;
829        #[inline]
830        fn len(&self) -> usize {
831            (**self).len()
832        }
833    }
834
835    impl<S: SliceByValueGet + ?Sized> SliceByValueGet for Arc<S> {
836        fn get_value(&self, index: usize) -> Option<Self::Value> {
837            (**self).get_value(index)
838        }
839        fn index_value(&self, index: usize) -> Self::Value {
840            (**self).index_value(index)
841        }
842        unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
843            (**self).get_value_unchecked(index)
844        }
845    }
846    impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Arc<S> {
847        type Subslice = S::Subslice;
848    }
849
850    impl<S: SliceByValue + ?Sized> SliceByValue for Rc<S> {
851        type Value = S::Value;
852        #[inline]
853        fn len(&self) -> usize {
854            (**self).len()
855        }
856    }
857
858    impl<S: SliceByValueGet + ?Sized> SliceByValueGet for Rc<S> {
859        fn get_value(&self, index: usize) -> Option<Self::Value> {
860            (**self).get_value(index)
861        }
862        fn index_value(&self, index: usize) -> Self::Value {
863            (**self).index_value(index)
864        }
865        unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
866            (**self).get_value_unchecked(index)
867        }
868    }
869
870    impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Rc<S> {
871        type Subslice = S::Subslice;
872    }
873
874    macro_rules! impl_range_arc_and_rc {
875        ($range:ty) => {
876            impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
877                for Rc<S>
878            {
879                #[inline]
880                fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
881                    (**self).get_subslice(index)
882                }
883
884                #[inline]
885                fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
886                    (**self).index_subslice(index)
887                }
888
889                #[inline]
890                unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
891                    unsafe { (**self).get_subslice_unchecked(index) }
892                }
893            }
894            impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
895                for Arc<S>
896            {
897                #[inline]
898                fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
899                    (**self).get_subslice(index)
900                }
901
902                #[inline]
903                fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
904                    (**self).index_subslice(index)
905                }
906
907                #[inline]
908                unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
909                    unsafe { (**self).get_subslice_unchecked(index) }
910                }
911            }
912        };
913    }
914
915    impl_range_arc_and_rc!(RangeFull);
916    impl_range_arc_and_rc!(RangeFrom<usize>);
917    impl_range_arc_and_rc!(RangeTo<usize>);
918    impl_range_arc_and_rc!(Range<usize>);
919    impl_range_arc_and_rc!(RangeInclusive<usize>);
920    impl_range_arc_and_rc!(RangeToInclusive<usize>);
921}
922
923#[cfg(test)]
924mod tests {
925
926    use super::*;
927
928    #[test]
929    #[allow(clippy::reversed_empty_ranges)]
930    fn test_good_ranges() {
931        // Range
932        assert!((0..1).is_valid(1));
933        assert!(!(1..0).is_valid(1));
934        assert!(!(0..1).is_valid(0));
935
936        // RangeFrom
937        assert!((0..).is_valid(1));
938        assert!((1..).is_valid(1));
939        assert!(!(2..).is_valid(1));
940
941        // RangeFull
942        assert!((..).is_valid(0));
943        assert!((..).is_valid(1));
944
945        // RangeInclusive
946        assert!((0..=1).is_valid(2));
947        assert!(!(1..=0).is_valid(2));
948        assert!(!(0..=1).is_valid(1));
949
950        // RangeTo
951        assert!((..0).is_valid(1));
952        assert!((..1).is_valid(1));
953        assert!(!(..2).is_valid(1));
954
955        // RangeToInclusive
956        assert!((..=0).is_valid(2));
957        assert!((..=1).is_valid(2));
958        assert!(!(..=2).is_valid(2));
959    }
960}