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, the length of the slice, and provides
20//! read-only access. Additional functionality is provided by the
21//! [`SliceByValueMut`] trait, which provides mutation methods. Note that,
22//! contrarily to the standard slices, replacement can be obtained by a pair of
23//! get/set operations: [`SliceByValueMut`] provides both methods for
24//! efficiency.
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//! unsafe fn get_value_unchecked(&self, index: usize) -> usize {
52//! unsafe { self.0.get_value_unchecked(index) as usize }
53//! }
54//! }
55//!
56//! fn f(slice_by_value: impl SliceByValue<Value = usize>, index: usize) -> usize {
57//! slice_by_value.index_value(index)
58//! }
59//!
60//! fn main() {
61//! let vec = vec![0_u8, 1, 2, 3];
62//! let slice_by_value = CompSlice(&vec);
63//! // Note that we can pass a reference
64//! assert_eq!(f(&slice_by_value, 0), 0);
65//! assert_eq!(f(&slice_by_value, 1), 1);
66//! assert_eq!(f(&slice_by_value, 2), 2);
67//! assert_eq!(f(&slice_by_value, 3), 3);
68//! }
69//!
70//! ```
71//! In this example, instead, we define functionally a slice containing the
72//! first 100 squares:
73//!
74//! ```rust
75//! use value_traits::slices::*;
76//!
77//! struct Squares();
78//!
79//! impl SliceByValue for Squares {
80//! type Value = usize;
81//! fn len(&self) -> usize {
82//! 100
83//! }
84//!
85//! unsafe fn get_value_unchecked(&self, index: usize) -> usize {
86//! index * index
87//! }
88//! }
89//!
90//! fn f(slice_by_value: &impl SliceByValue<Value = usize>, index: usize) -> usize {
91//! slice_by_value.index_value(index)
92//! }
93//!
94//! fn main() {
95//! let squares = Squares();
96//! for i in 0..100 {
97//! assert_eq!(squares.index_value(i), i * i);
98//! }
99//! }
100//! ```
101
102use core::ops::{
103 Range, RangeBounds, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
104};
105
106use crate::{ImplBound, Ref};
107
108/// Error type returned when [`try_chunks_mut`](SliceByValueMut::try_chunks_mut)
109/// is not supported by a type.
110///
111/// This error is typically returned by derived subslice types which cannot
112/// provide mutable chunks due to their implementation constraints.
113#[derive(Debug, Clone, Copy, PartialEq, Eq)]
114pub struct ChunksMutNotSupported;
115
116impl core::fmt::Display for ChunksMutNotSupported {
117 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118 write!(f, "try_chunks_mut is not supported on subslices")
119 }
120}
121
122impl core::error::Error for ChunksMutNotSupported {}
123
124#[inline(always)]
125fn assert_index(index: usize, len: usize) {
126 assert!(
127 index < len,
128 "index out of bounds: the len is {len} but the index is {index}",
129 );
130}
131
132#[inline(always)]
133fn assert_range(range: &impl ComposeRange, len: usize) {
134 assert!(
135 range.is_valid(len),
136 "range {range:?} out of range for slice of length {len}",
137 );
138}
139
140/// Read-only by-value slice trait.
141///
142/// The only methods that must be implemented are
143/// [`get_value_unchecked`](`SliceByValue::get_value_unchecked`) and
144/// [`len`](`SliceByValue::len`).
145pub trait SliceByValue {
146 /// The type of the values in the slice.
147 type Value;
148
149 /// See [`slice::len`].
150 fn len(&self) -> usize;
151
152 /// See [`slice::is_empty`].
153 fn is_empty(&self) -> bool {
154 self.len() == 0
155 }
156 /// See [the `Index` implementation for slices](slice#impl-Index%3CI%3E-for-%5BT%5D).
157 fn index_value(&self, index: usize) -> Self::Value {
158 assert_index(index, self.len());
159 // SAFETY: index is within bounds
160 unsafe { self.get_value_unchecked(index) }
161 }
162
163 /// See [`slice::get_unchecked`].
164 ///
165 /// For a safe alternative see [`get_value`](SliceByValue::get_value)
166 /// or [`index_value`](SliceByValue::index_value).
167 ///
168 /// # Safety
169 ///
170 /// The index must be within bounds.
171 unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value;
172
173 /// See [`slice::get`].
174 fn get_value(&self, index: usize) -> Option<Self::Value> {
175 if index < self.len() {
176 // SAFETY: index is within bounds
177 let value = unsafe { self.get_value_unchecked(index) };
178 Some(value)
179 } else {
180 None
181 }
182 }
183}
184
185impl<S: SliceByValue + ?Sized> SliceByValue for &S {
186 type Value = S::Value;
187
188 #[inline]
189 fn len(&self) -> usize {
190 (**self).len()
191 }
192
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: SliceByValue + ?Sized> SliceByValue for &mut S {
205 type Value = S::Value;
206
207 #[inline]
208 fn len(&self) -> usize {
209 (**self).len()
210 }
211
212 fn get_value(&self, index: usize) -> Option<Self::Value> {
213 (**self).get_value(index)
214 }
215 fn index_value(&self, index: usize) -> Self::Value {
216 (**self).index_value(index)
217 }
218 unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
219 unsafe { (**self).get_value_unchecked(index) }
220 }
221}
222
223/// Mutable by-value slice trait providing setting and replacement methods.
224///
225/// This trait provides both [`set_value`](SliceByValueMut::set_value) (for setting
226/// without returning the previous value) and [`replace_value`](SliceByValueMut::replace_value)
227/// (for setting and returning the previous value).
228///
229/// The only methods that must be implemented are
230/// [`set_value_unchecked`](`SliceByValueMut::set_value_unchecked`) and
231/// [`replace_value_unchecked`](`SliceByValueMut::replace_value_unchecked`).
232pub trait SliceByValueMut: SliceByValue {
233 /// Sets the value at the given index to the given value without doing
234 /// bounds checking.
235 ///
236 /// For a safe alternative see [`set_value`](SliceByValueMut::set_value).
237 ///
238 /// # Safety
239 ///
240 /// The index must be within bounds.
241 unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value);
242
243 /// Sets the value at the given index to the given value.
244 ///
245 /// # Panics
246 ///
247 /// This method will panic if the index is not within bounds.
248 fn set_value(&mut self, index: usize, value: Self::Value) {
249 assert_index(index, self.len());
250 // SAFETY: index is within bounds
251 unsafe {
252 self.set_value_unchecked(index, value);
253 }
254 }
255
256 /// Sets the value at the given index to the given value and
257 /// returns the previous value, without doing bounds checking.
258 ///
259 /// For a safe alternative see [`replace_value`](SliceByValueMut::replace_value).
260 ///
261 /// This default implementation uses
262 /// [`get_value_unchecked`](SliceByValue::get_value_unchecked) and
263 /// [`set_value_unchecked`](SliceByValueMut::set_value_unchecked).
264 ///
265 /// # Safety
266 ///
267 /// The index must be within bounds.
268 unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value {
269 let old_value = unsafe { self.get_value_unchecked(index) };
270 unsafe { self.set_value_unchecked(index, value) };
271 old_value
272 }
273
274 /// Sets the value at the given index to the given value and
275 /// returns the previous value.
276 ///
277 /// # Panics
278 ///
279 /// This method will panic if the index is not within bounds.
280 fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
281 assert_index(index, self.len());
282 // SAFETY: index is within bounds
283 unsafe { self.replace_value_unchecked(index, value) }
284 }
285
286 /// Copy part of the content of the slice to another slice.
287 ///
288 /// At most `len` elements are copied, compatibly with the elements
289 /// available in both vectors.
290 ///
291 /// # Arguments
292 ///
293 /// * `from`: the index of the first element to copy.
294 ///
295 /// * `dst`: the destination vector.
296 ///
297 /// * `to`: the index of the first element in the destination vector.
298 ///
299 /// * `len`: the maximum number of elements to copy.
300 ///
301 /// # Implementation Notes
302 ///
303 /// The default implementation is a simple loop that copies the elements one
304 /// by one. It is expected to be implemented in a more efficient way.
305 fn copy(&self, from: usize, dst: &mut Self, to: usize, len: usize) {
306 // Reduce len to the elements available in both vectors
307 let len = Ord::min(
308 Ord::min(len, dst.len().saturating_sub(to)),
309 self.len().saturating_sub(from),
310 );
311 for i in 0..len {
312 dst.set_value(to + i, self.index_value(from + i));
313 }
314 }
315
316 /// Applies a function to all elements of the slice in place without
317 /// checks.
318 ///
319 /// This method is semantically equivalent to:
320 /// ```ignore
321 /// for i in 0..self.len() {
322 /// self.set_value_unchecked(i, f(self.get_value_unchecked(i)));
323 /// }
324 /// ```
325 /// and this is indeed the default implementation.
326 ///
327 /// See [`apply_in_place`](SliceByValueMut::apply_in_place) for examples.
328 ///
329 /// # Safety
330 ///
331 /// The function must return a value that agrees with the safety
332 /// requirements of
333 /// [`set_value_unchecked`](SliceByValueMut::set_value_unchecked).
334 unsafe fn apply_in_place_unchecked<F>(&mut self, mut f: F)
335 where
336 F: FnMut(Self::Value) -> Self::Value,
337 {
338 for idx in 0..self.len() {
339 let value = unsafe { self.get_value_unchecked(idx) };
340 let new_value = f(value);
341 unsafe { self.set_value_unchecked(idx, new_value) };
342 }
343 }
344
345 /// Applies a function to all elements of the slice in place.
346 ///
347 /// This method is semantically equivalent to:
348 /// ```ignore
349 /// for i in 0..self.len() {
350 /// self.set_value(i, f(self.index_value(i)));
351 /// }
352 /// ```
353 /// and this is indeed the default implementation.
354 ///
355 /// The function is applied from the first element to the last: thus,
356 /// it possible to compute cumulative sums as follows:
357 ///
358 /// ```
359 /// use value_traits::slices::SliceByValueMut;
360 /// let mut vec = vec![0; 10];
361 ///
362 /// for i in 0..10 {
363 /// vec.set_value(i, i as u16);
364 /// }
365 ///
366 /// let mut total = 0;
367 /// vec.apply_in_place(|x| {
368 /// total += x;
369 /// total
370 /// });
371 /// ```
372 fn apply_in_place<F>(&mut self, mut f: F)
373 where
374 F: FnMut(Self::Value) -> Self::Value,
375 {
376 for idx in 0..self.len() {
377 let value = unsafe { self.get_value_unchecked(idx) };
378 let new_value = f(value);
379 unsafe { self.set_value_unchecked(idx, new_value) };
380 }
381 }
382
383 /// The iterator type returned by [`try_chunks_mut`](SliceByValueMut::try_chunks_mut).
384 type ChunksMut<'a>: Iterator<Item: SliceByValueMut<Value = Self::Value>>
385 where
386 Self: 'a;
387
388 /// The error type returned by [`try_chunks_mut`](SliceByValueMut::try_chunks_mut).
389 ///
390 /// For implementations that always succeed (like slices, arrays, and vectors),
391 /// this should be [`core::convert::Infallible`].
392 type ChunksMutError: core::fmt::Debug;
393
394 /// Tries and returns an iterator over mutable chunks of a slice, starting
395 /// at the beginning of the slice.
396 ///
397 /// This might not always be possible; implementations must document when
398 /// the method will success (see, for example, [the implementation for
399 /// `BitFieldVec`](https://docs.rs/sux/latest/sux/bits/bit_field_vec/struct.BitFieldVec.html#impl-BitFieldSliceMut<W>-for-BitFieldVec<W,+B>)).
400 ///
401 /// When the slice len is not evenly divided by the chunk size, the last
402 /// chunk of the iteration will be the remainder.
403 ///
404 /// # Errors
405 ///
406 /// Returns an error of type [`ChunksMutError`](SliceByValueMut::ChunksMutError)
407 /// if the operation is not supported by the implementation. For example,
408 /// derived subslice types return [`ChunksMutNotSupported`].
409 ///
410 /// # Examples
411 ///
412 /// ```
413 /// use value_traits::slices::SliceByValueMut;
414 /// let mut b = vec![4, 500, 2, 3, 1];
415 /// for mut c in b.try_chunks_mut(2)? {
416 /// c.set_value(0, 5);
417 /// }
418 /// assert_eq!(b, vec![5, 500, 5, 3, 5]);
419 /// # Ok::<(), Box<dyn std::error::Error>>(())
420 /// ```
421 fn try_chunks_mut(
422 &mut self,
423 chunk_size: usize,
424 ) -> Result<Self::ChunksMut<'_>, Self::ChunksMutError>;
425}
426
427impl<S: SliceByValueMut + ?Sized> SliceByValueMut for &mut S {
428 fn set_value(&mut self, index: usize, value: Self::Value) {
429 (**self).set_value(index, value);
430 }
431 unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
432 unsafe {
433 (**self).set_value_unchecked(index, value);
434 }
435 }
436 fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
437 (**self).replace_value(index, value)
438 }
439 unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value {
440 unsafe { (**self).replace_value_unchecked(index, value) }
441 }
442
443 type ChunksMut<'a>
444 = S::ChunksMut<'a>
445 where
446 Self: 'a;
447
448 type ChunksMutError = S::ChunksMutError;
449
450 fn try_chunks_mut(
451 &mut self,
452 chunk_size: usize,
453 ) -> Result<Self::ChunksMut<'_>, Self::ChunksMutError> {
454 (**self).try_chunks_mut(chunk_size)
455 }
456}
457
458/// A range that can check whether it is within the bounds of a slice, and
459/// intersect itself with another range.
460///
461/// This trait is implemented for the six Rust range types in [`core::ops`],
462/// making it possible to treat them uniformly in implementations, and in
463/// particular in procedural macros.
464pub trait ComposeRange: RangeBounds<usize> + core::fmt::Debug {
465 /// Returns `true` if the range is within the bounds of a slice of given
466 /// length
467 fn is_valid(&self, len: usize) -> bool;
468
469 /// Returns a new range that is the composition of `base` with the range.
470 ///
471 /// The resulting range is guaranteed to be contained in `base` if `self` [is
472 /// valid](ComposeRange::is_valid) for `base.len()`.
473 ///
474 /// ```rust
475 /// use value_traits::slices::ComposeRange;
476 ///
477 /// assert_eq!((2..5).compose(10..20), 12..15);
478 /// assert_eq!((2..=5).compose(10..20), 12..16);
479 /// assert_eq!((..5).compose(10..20), 10..15);
480 /// assert_eq!((..=5).compose(10..20), 10..16);
481 /// assert_eq!((2..).compose(10..20), 12..20);
482 /// assert_eq!((..).compose(10..20), 10..20);
483 /// ```
484 fn compose(&self, base: Range<usize>) -> Range<usize>;
485}
486
487impl ComposeRange for Range<usize> {
488 fn is_valid(&self, len: usize) -> bool {
489 self.start <= len && self.end <= len && self.start <= self.end
490 }
491
492 fn compose(&self, base: Range<usize>) -> Range<usize> {
493 (base.start + self.start)..(base.start + self.end)
494 }
495}
496
497impl ComposeRange for RangeFrom<usize> {
498 fn is_valid(&self, len: usize) -> bool {
499 self.start <= len
500 }
501
502 fn compose(&self, base: Range<usize>) -> Range<usize> {
503 (base.start + self.start)..base.end
504 }
505}
506
507impl ComposeRange for RangeFull {
508 fn is_valid(&self, _len: usize) -> bool {
509 true
510 }
511
512 fn compose(&self, base: Range<usize>) -> Range<usize> {
513 base
514 }
515}
516
517impl ComposeRange for RangeInclusive<usize> {
518 fn is_valid(&self, len: usize) -> bool {
519 *self.start() < len && *self.end() < len && self.start() <= self.end()
520 }
521
522 fn compose(&self, base: Range<usize>) -> Range<usize> {
523 (base.start + self.start())..(base.start + self.end() + 1)
524 }
525}
526
527impl ComposeRange for RangeTo<usize> {
528 fn is_valid(&self, len: usize) -> bool {
529 self.end <= len
530 }
531
532 fn compose(&self, base: Range<usize>) -> Range<usize> {
533 base.start..(base.start + self.end)
534 }
535}
536
537impl ComposeRange for RangeToInclusive<usize> {
538 fn is_valid(&self, len: usize) -> bool {
539 self.end < len
540 }
541
542 fn compose(&self, base: Range<usize>) -> Range<usize> {
543 base.start..(base.start + self.end + 1)
544 }
545}
546
547/// A GAT-like trait specifying the subslice type.
548///
549/// It implicitly restricts the lifetime `'a` used in `SliceByValueRange` to be
550/// `where Self: 'a`. Moreover, it requires [`SliceByValue`].
551///
552/// As in other theoretical applications of GATs (Generic Associated Types),
553/// like [lenders](https://crates.io/crates/lender), using a GAT to express the
554/// type of a subslice is problematic because when bounding the type itself in a
555/// `where` clause using Higher-Rank Trait Bounds (HRTBs) the bound must be true
556/// for all lifetimes, including `'static`, resulting in the sliced type having
557/// to be `'static` as well.
558///
559/// This is a result of HRTBs not having a way to express qualifiers (`for<'any
560/// where Self: 'any> Self: Trait`) and effectively making HRTBs only useful
561/// when you want to express a trait constraint on *all* lifetimes, including
562/// `'static` (`for<'all> Self: trait`)
563///
564/// Please see [Sabrina's Blog][1] for more information, and how a trait like
565/// this can be used to solve it by implicitly restricting HRTBs.
566///
567/// [1]:
568/// <https://sabrinajewson.org/blog/the-better-alternative-to-lifetime-gats>
569pub trait SliceByValueSubsliceGat<'a, __Implicit: ImplBound = Ref<'a, Self>>: SliceByValue {
570 /// The type of the subslice.
571 type Subslice: 'a + SliceByValue<Value = Self::Value> + SliceByValueSubslice;
572}
573
574/// A convenience type representing the type of subslice
575/// of a type implementing [`SliceByValueSubsliceGat`].
576#[allow(type_alias_bounds)] // yeah the type alias bounds are not enforced, but they are useful for documentation
577pub type Subslice<'a, T: SliceByValueSubsliceGat<'a>> =
578 <T as SliceByValueSubsliceGat<'a>>::Subslice;
579
580impl<'a, T: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for &T {
581 type Subslice = T::Subslice;
582}
583
584impl<'a, T: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for &mut T {
585 type Subslice = T::Subslice;
586}
587
588/// A trait implementing subslicing for a specific range parameter.
589///
590/// The user should never see this trait. [`SliceByValueSubslice`] combines all
591/// instances of this trait with `R` equal to the various kind of standard
592/// ranges ([`core::ops::Range`], [`core::ops::RangeFull`], etc.).
593///
594/// The only method that must be implemented is
595/// [`get_subslice_unchecked`](`SliceByValueSubsliceRange::get_subslice_unchecked`).
596pub trait SliceByValueSubsliceRange<R: ComposeRange>: for<'a> SliceByValueSubsliceGat<'a> {
597 /// See [the `Index` implementation for slices](slice#impl-Index%3CI%3E-for-%5BT%5D).
598 fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
599 assert_range(&range, self.len());
600 unsafe {
601 // SAFETY: range is within bounds
602 self.get_subslice_unchecked(range)
603 }
604 }
605
606 /// See [`slice::get_unchecked`].
607 ///
608 /// For a safe alternative see
609 /// [`get_subslice`](SliceByValueSubsliceRange::get_subslice) or
610 /// [`index_subslice`](SliceByValueSubsliceRange::index_subslice).
611 ///
612 /// # Safety
613 ///
614 /// The range must be within bounds.
615 unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self>;
616
617 /// See [`slice::get`].
618 fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
619 if range.is_valid(self.len()) {
620 let subslice = unsafe { self.get_subslice_unchecked(range) };
621 Some(subslice)
622 } else {
623 None
624 }
625 }
626}
627
628impl<R: ComposeRange, S: SliceByValueSubsliceRange<R> + ?Sized> SliceByValueSubsliceRange<R>
629 for &S
630{
631 fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
632 (**self).get_subslice(range)
633 }
634 fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
635 (**self).index_subslice(range)
636 }
637 unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self> {
638 unsafe { (**self).get_subslice_unchecked(range) }
639 }
640}
641impl<R: ComposeRange, S: SliceByValueSubsliceRange<R> + ?Sized> SliceByValueSubsliceRange<R>
642 for &mut S
643{
644 fn get_subslice(&self, range: R) -> Option<Subslice<'_, Self>> {
645 (**self).get_subslice(range)
646 }
647 fn index_subslice(&self, range: R) -> Subslice<'_, Self> {
648 (**self).index_subslice(range)
649 }
650 unsafe fn get_subslice_unchecked(&self, range: R) -> Subslice<'_, Self> {
651 unsafe { (**self).get_subslice_unchecked(range) }
652 }
653}
654
655/// A GAT-like trait specifying the mutable subslice type.
656///
657/// See [`SliceByValueSubsliceGat`].
658pub trait SliceByValueSubsliceGatMut<'a, __Implicit: ImplBound = Ref<'a, Self>>:
659 SliceByValueMut
660{
661 /// The type of the mutable subslice.
662 type SubsliceMut: 'a
663 + SliceByValueMut<Value = Self::Value>
664 + SliceByValueSubsliceGatMut<'a, SubsliceMut = Self::SubsliceMut> // recursion
665 + SliceByValueSubsliceMut;
666}
667
668/// A convenience type representing the type of subslice
669/// of a type implementing [`SliceByValueSubsliceGatMut`].
670#[allow(type_alias_bounds)] // yeah the type alias bounds are not enforced, but they are useful for documentation
671pub type SubsliceMut<'a, T: SliceByValueSubsliceGatMut<'a>> =
672 <T as SliceByValueSubsliceGatMut<'a>>::SubsliceMut;
673
674impl<'a, T: SliceByValueSubsliceGatMut<'a> + ?Sized> SliceByValueSubsliceGatMut<'a> for &mut T {
675 type SubsliceMut = T::SubsliceMut;
676}
677
678/// A trait implementing mutable subslicing for a specific range parameter.
679///
680/// The user should never see this trait. [`SliceByValueSubsliceMut`] combines
681/// all instances of this trait with `R` equal to the various kind of standard
682/// ranges ([`core::ops::Range`], [`core::ops::RangeFull`], etc.).
683///
684/// The only method that must be implemented is
685/// [`get_subslice_unchecked_mut`](`SliceByValueSubsliceRangeMut::get_subslice_unchecked_mut`).
686pub trait SliceByValueSubsliceRangeMut<R: ComposeRange>:
687 for<'a> SliceByValueSubsliceGatMut<'a>
688{
689 /// See [the `Index` implementation for slices](slice#impl-Index%3CI%3E-for-%5BT%5D).
690 fn index_subslice_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
691 assert_range(&range, self.len());
692 unsafe {
693 // SAFETY: range is within bounds
694 self.get_subslice_unchecked_mut(range)
695 }
696 }
697
698 /// See [`slice::get_unchecked`].
699 ///
700 /// For a safe alternative see
701 /// [`get_subslice_mut`](SliceByValueSubsliceRangeMut::get_subslice_mut) or
702 /// [`index_subslice_mut`](SliceByValueSubsliceRangeMut::index_subslice_mut).
703 ///
704 /// # Safety
705 ///
706 /// The range must be within bounds.
707 unsafe fn get_subslice_unchecked_mut(&mut self, range: R) -> SubsliceMut<'_, Self>;
708
709 /// See [`slice::get`].
710 fn get_subslice_mut(&mut self, range: R) -> Option<SubsliceMut<'_, Self>> {
711 if range.is_valid(self.len()) {
712 // SAFETY: range is within bounds
713 let subslice_mut = unsafe { self.get_subslice_unchecked_mut(range) };
714 Some(subslice_mut)
715 } else {
716 None
717 }
718 }
719}
720
721impl<R: ComposeRange, S: SliceByValueSubsliceRangeMut<R> + ?Sized> SliceByValueSubsliceRangeMut<R>
722 for &mut S
723{
724 fn get_subslice_mut(&mut self, range: R) -> Option<SubsliceMut<'_, Self>> {
725 (**self).get_subslice_mut(range)
726 }
727 fn index_subslice_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
728 (**self).index_subslice_mut(range)
729 }
730 unsafe fn get_subslice_unchecked_mut(&mut self, range: R) -> SubsliceMut<'_, Self> {
731 unsafe { (**self).get_subslice_unchecked_mut(range) }
732 }
733}
734
735/// A convenience trait combining all instances of [`SliceByValueSubsliceRange`]
736/// with `R` equal to the various kind of standard ranges ([`core::ops::Range`],
737/// [`core::ops::RangeFull`], etc.).
738///
739/// A blanket implementation automatically implements the trait if all necessary
740/// implementations of [`SliceByValueSubsliceRange`] are available.
741///
742/// ## Binding the Subslice Type
743///
744/// To bind the iterator type you need to use higher-rank trait
745/// bounds, as in:
746///
747/// ```rust
748/// use value_traits::slices::*;
749///
750/// fn f<S>(s: S) where
751/// S: SliceByValueSubslice + for<'a> SliceByValueSubsliceGat<'a, Subslice = &'a [u8]>,
752/// {
753/// let _: &[u8] = s.index_subslice(0..10);
754/// }
755/// ```
756///
757/// The bound applies uniformly to all type of ranges.
758///
759/// You can also bind the subslice using traits:
760///
761/// ```rust
762/// use value_traits::slices::*;
763///
764/// fn f<S>(s: S) where
765/// S: SliceByValueSubslice + for<'a> SliceByValueSubsliceGat<'a, Subslice: AsRef<[u8]>>,
766/// {
767/// let _: &[u8] = s.index_subslice(0..10).as_ref();
768/// }
769/// ```
770///
771/// In this case, you can equivalently use the [`Subslice`] type alias, which might
772/// be more concise:
773///
774/// ```rust
775/// use value_traits::slices::*;
776///
777/// fn f<S>(s: S) where
778/// S: SliceByValueSubslice,
779/// for<'a> Subslice<'a, S>: AsRef<[u8]>,
780/// {
781/// let _: &[u8] = s.index_subslice(0..10).as_ref();
782/// }
783/// ```
784pub trait SliceByValueSubslice:
785 SliceByValueSubsliceRange<Range<usize>>
786 + SliceByValueSubsliceRange<RangeFrom<usize>>
787 + SliceByValueSubsliceRange<RangeFull>
788 + SliceByValueSubsliceRange<RangeInclusive<usize>>
789 + SliceByValueSubsliceRange<RangeTo<usize>>
790 + SliceByValueSubsliceRange<RangeToInclusive<usize>>
791{
792}
793
794impl<U> SliceByValueSubslice for U
795where
796 U: SliceByValueSubsliceRange<Range<usize>>,
797 U: SliceByValueSubsliceRange<RangeFrom<usize>>,
798 U: SliceByValueSubsliceRange<RangeFull>,
799 U: SliceByValueSubsliceRange<RangeInclusive<usize>>,
800 U: SliceByValueSubsliceRange<RangeTo<usize>>,
801 U: SliceByValueSubsliceRange<RangeToInclusive<usize>>,
802{
803}
804
805/// A convenience trait combining all instances of
806/// [`SliceByValueSubsliceRangeMut`] with `R` equal to the various kind of
807/// standard ranges ([`core::ops::Range`], [`core::ops::RangeFull`], etc.).
808///
809/// A blanket implementation automatically implements the trait if all necessary
810/// implementations of [`SliceByValueSubsliceMut`] are available.
811///
812/// ## Binding the Subslice Type
813///
814/// To bind the iterator type you need to use higher-rank trait
815/// bounds, as in:
816///
817/// ```rust
818/// use value_traits::slices::*;
819///
820/// fn f<S>(mut s: S) where
821/// S: SliceByValueSubsliceMut + for<'a> SliceByValueSubsliceGatMut<'a, SubsliceMut = &'a mut [u8]>,
822/// {
823/// let _: &mut [u8] = s.index_subslice_mut(0..10);
824/// }
825/// ```
826///
827/// The bound applies uniformly to all type of ranges.
828///
829/// You can also bind the subslice using traits:
830///
831/// ```rust
832/// use value_traits::slices::*;
833///
834/// fn f<S>(mut s: S) where
835/// S: SliceByValueSubsliceMut + for<'a> SliceByValueSubsliceGatMut<'a, SubsliceMut: AsMut<[u8]>>,
836/// {
837/// let _: &mut [u8] = s.index_subslice_mut(0..10).as_mut();
838/// }
839/// ```
840///
841/// In this case, you can equivalently use the [`SubsliceMut`] type alias, which might
842/// be more concise:
843///
844/// ```rust
845/// use value_traits::slices::*;
846///
847/// fn f<S>(mut s: S) where
848/// S: SliceByValueSubsliceMut,
849/// for<'a> SubsliceMut<'a, S>: AsMut<[u8]>,
850/// {
851/// let _: &mut [u8] = s.index_subslice_mut(0..10).as_mut();
852/// }
853/// ```
854pub trait SliceByValueSubsliceMut:
855 SliceByValueSubsliceRangeMut<Range<usize>>
856 + SliceByValueSubsliceRangeMut<RangeFrom<usize>>
857 + SliceByValueSubsliceRangeMut<RangeFull>
858 + SliceByValueSubsliceRangeMut<RangeInclusive<usize>>
859 + SliceByValueSubsliceRangeMut<RangeTo<usize>>
860 + SliceByValueSubsliceRangeMut<RangeToInclusive<usize>>
861{
862}
863
864impl<U> SliceByValueSubsliceMut for U
865where
866 U: SliceByValueSubsliceRangeMut<Range<usize>>,
867 U: SliceByValueSubsliceRangeMut<RangeFrom<usize>>,
868 U: SliceByValueSubsliceRangeMut<RangeFull>,
869 U: SliceByValueSubsliceRangeMut<RangeInclusive<usize>>,
870 U: SliceByValueSubsliceRangeMut<RangeTo<usize>>,
871 U: SliceByValueSubsliceRangeMut<RangeToInclusive<usize>>,
872{
873}
874
875#[cfg(feature = "alloc")]
876mod alloc_impls {
877 use super::*;
878 #[cfg(all(feature = "alloc", not(feature = "std")))]
879 use alloc::boxed::Box;
880
881 impl<S: SliceByValue + ?Sized> SliceByValue for Box<S> {
882 type Value = S::Value;
883
884 #[inline]
885 fn len(&self) -> usize {
886 (**self).len()
887 }
888
889 fn get_value(&self, index: usize) -> Option<Self::Value> {
890 (**self).get_value(index)
891 }
892 fn index_value(&self, index: usize) -> Self::Value {
893 (**self).index_value(index)
894 }
895 unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
896 unsafe { (**self).get_value_unchecked(index) }
897 }
898 }
899
900 impl<S: SliceByValueMut + ?Sized> SliceByValueMut for Box<S> {
901 fn set_value(&mut self, index: usize, value: Self::Value) {
902 (**self).set_value(index, value);
903 }
904 unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
905 unsafe {
906 (**self).set_value_unchecked(index, value);
907 }
908 }
909 fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
910 (**self).replace_value(index, value)
911 }
912 unsafe fn replace_value_unchecked(
913 &mut self,
914 index: usize,
915 value: Self::Value,
916 ) -> Self::Value {
917 unsafe { (**self).replace_value_unchecked(index, value) }
918 }
919
920 type ChunksMut<'a>
921 = S::ChunksMut<'a>
922 where
923 Self: 'a;
924
925 type ChunksMutError = S::ChunksMutError;
926
927 fn try_chunks_mut(
928 &mut self,
929 chunk_size: usize,
930 ) -> Result<Self::ChunksMut<'_>, Self::ChunksMutError> {
931 (**self).try_chunks_mut(chunk_size)
932 }
933 }
934
935 impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Box<S> {
936 type Subslice = S::Subslice;
937 }
938 impl<'a, S: SliceByValueSubsliceGatMut<'a> + ?Sized> SliceByValueSubsliceGatMut<'a> for Box<S> {
939 type SubsliceMut = S::SubsliceMut;
940 }
941
942 macro_rules! impl_range_alloc {
943 ($range:ty) => {
944 impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
945 for Box<S>
946 {
947 #[inline]
948 fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
949 (**self).get_subslice(index)
950 }
951
952 #[inline]
953 fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
954 (**self).index_subslice(index)
955 }
956
957 #[inline]
958 unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
959 unsafe { (**self).get_subslice_unchecked(index) }
960 }
961 }
962 impl<S: SliceByValueSubsliceRangeMut<$range> + ?Sized>
963 SliceByValueSubsliceRangeMut<$range> for Box<S>
964 {
965 #[inline]
966 fn get_subslice_mut(&mut self, index: $range) -> Option<SubsliceMut<'_, Self>> {
967 (**self).get_subslice_mut(index)
968 }
969
970 #[inline]
971 fn index_subslice_mut(&mut self, index: $range) -> SubsliceMut<'_, Self> {
972 (**self).index_subslice_mut(index)
973 }
974
975 #[inline]
976 unsafe fn get_subslice_unchecked_mut(
977 &mut self,
978 index: $range,
979 ) -> SubsliceMut<'_, Self> {
980 unsafe { (**self).get_subslice_unchecked_mut(index) }
981 }
982 }
983 };
984 }
985
986 impl_range_alloc!(RangeFull);
987 impl_range_alloc!(RangeFrom<usize>);
988 impl_range_alloc!(RangeTo<usize>);
989 impl_range_alloc!(Range<usize>);
990 impl_range_alloc!(RangeInclusive<usize>);
991 impl_range_alloc!(RangeToInclusive<usize>);
992}
993
994#[cfg(feature = "std")]
995mod std_impls {
996 use super::*;
997 use std::{rc::Rc, sync::Arc};
998
999 impl<S: SliceByValue + ?Sized> SliceByValue for Arc<S> {
1000 type Value = S::Value;
1001
1002 #[inline]
1003 fn len(&self) -> usize {
1004 (**self).len()
1005 }
1006
1007 fn get_value(&self, index: usize) -> Option<Self::Value> {
1008 (**self).get_value(index)
1009 }
1010 fn index_value(&self, index: usize) -> Self::Value {
1011 (**self).index_value(index)
1012 }
1013 unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
1014 unsafe { (**self).get_value_unchecked(index) }
1015 }
1016 }
1017 impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Arc<S> {
1018 type Subslice = S::Subslice;
1019 }
1020
1021 impl<S: SliceByValue + ?Sized> SliceByValue for Rc<S> {
1022 type Value = S::Value;
1023
1024 #[inline]
1025 fn len(&self) -> usize {
1026 (**self).len()
1027 }
1028
1029 fn get_value(&self, index: usize) -> Option<Self::Value> {
1030 (**self).get_value(index)
1031 }
1032 fn index_value(&self, index: usize) -> Self::Value {
1033 (**self).index_value(index)
1034 }
1035 unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
1036 unsafe { (**self).get_value_unchecked(index) }
1037 }
1038 }
1039
1040 impl<'a, S: SliceByValueSubsliceGat<'a> + ?Sized> SliceByValueSubsliceGat<'a> for Rc<S> {
1041 type Subslice = S::Subslice;
1042 }
1043
1044 macro_rules! impl_range_arc_and_rc {
1045 ($range:ty) => {
1046 impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
1047 for Rc<S>
1048 {
1049 #[inline]
1050 fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
1051 (**self).get_subslice(index)
1052 }
1053
1054 #[inline]
1055 fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
1056 (**self).index_subslice(index)
1057 }
1058
1059 #[inline]
1060 unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
1061 unsafe { (**self).get_subslice_unchecked(index) }
1062 }
1063 }
1064 impl<S: SliceByValueSubsliceRange<$range> + ?Sized> SliceByValueSubsliceRange<$range>
1065 for Arc<S>
1066 {
1067 #[inline]
1068 fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
1069 (**self).get_subslice(index)
1070 }
1071
1072 #[inline]
1073 fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
1074 (**self).index_subslice(index)
1075 }
1076
1077 #[inline]
1078 unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
1079 unsafe { (**self).get_subslice_unchecked(index) }
1080 }
1081 }
1082 };
1083 }
1084
1085 impl_range_arc_and_rc!(RangeFull);
1086 impl_range_arc_and_rc!(RangeFrom<usize>);
1087 impl_range_arc_and_rc!(RangeTo<usize>);
1088 impl_range_arc_and_rc!(Range<usize>);
1089 impl_range_arc_and_rc!(RangeInclusive<usize>);
1090 impl_range_arc_and_rc!(RangeToInclusive<usize>);
1091}
1092
1093#[cfg(test)]
1094mod tests {
1095
1096 use super::*;
1097
1098 #[test]
1099 #[allow(clippy::reversed_empty_ranges)]
1100 fn test_good_ranges() {
1101 // Range
1102 assert!((0..1).is_valid(1));
1103 assert!(!(1..0).is_valid(1));
1104 assert!(!(0..1).is_valid(0));
1105
1106 // RangeFrom
1107 assert!((0..).is_valid(1));
1108 assert!((1..).is_valid(1));
1109 assert!(!(2..).is_valid(1));
1110
1111 // RangeFull
1112 assert!((..).is_valid(0));
1113 assert!((..).is_valid(1));
1114
1115 // RangeInclusive
1116 assert!((0..=1).is_valid(2));
1117 assert!(!(1..=0).is_valid(2));
1118 assert!(!(0..=1).is_valid(1));
1119
1120 // RangeTo
1121 assert!((..0).is_valid(1));
1122 assert!((..1).is_valid(1));
1123 assert!(!(..2).is_valid(1));
1124
1125 // RangeToInclusive
1126 assert!((..=0).is_valid(2));
1127 assert!((..=1).is_valid(2));
1128 assert!(!(..=2).is_valid(2));
1129 }
1130}