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