value_traits/impls/
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
9use core::{
10    iter::{Cloned, Skip},
11    ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
12};
13
14use crate::{
15    iter::{IterableByValue, IterableByValueFrom},
16    slices::{
17        SliceByValue, SliceByValueGet, SliceByValueRepl, SliceByValueSet, SliceByValueSubsliceGat,
18        SliceByValueSubsliceGatMut, SliceByValueSubsliceRange, SliceByValueSubsliceRangeMut,
19        Subslice, SubsliceMut,
20    },
21};
22
23impl<T> SliceByValue for [T] {
24    type Value = T;
25    #[inline]
26    fn len(&self) -> usize {
27        <[T]>::len(self)
28    }
29}
30
31// --- Implementations for standard slices [T] and usize index ---
32impl<T: Clone> SliceByValueGet for [T] {
33    #[inline]
34    fn get_value(&self, index: usize) -> Option<Self::Value> {
35        // slice.get returns Option<&T>, .cloned() converts to Option<T>
36        (*self).get(index).cloned()
37    }
38
39    #[inline]
40    fn index_value(&self, index: usize) -> Self::Value {
41        // Standard indexing panics on out-of-bounds.
42        // It returns &T, which we copy to return T.
43        self[index].clone()
44    }
45
46    #[inline]
47    unsafe fn get_value_unchecked(&self, index: usize) -> Self::Value {
48        // Safety: The caller must ensure that `*self` (the index) is in bounds.
49        // slice.get_unchecked returns &T, which we dereference and copy.
50        unsafe { (*self).get_unchecked(index).clone() }
51    }
52}
53
54impl<T: Clone> SliceByValueSet for [T] {
55    #[inline]
56    fn set_value(&mut self, index: usize, value: Self::Value) {
57        // Standard indexing panics on out-of-bounds.
58        self[index] = value;
59    }
60
61    #[inline]
62    unsafe fn set_value_unchecked(&mut self, index: usize, value: Self::Value) {
63        // Safety: The caller must ensure that `*self` (the index) is in bounds.
64        unsafe {
65            let elem = self.get_unchecked_mut(index);
66            *elem = value;
67        }
68    }
69}
70
71impl<T: Clone> SliceByValueRepl for [T] {
72    #[inline]
73    fn replace_value(&mut self, index: usize, value: Self::Value) -> Self::Value {
74        // Standard indexing panics on out-of-bounds.
75        // We get a mutable reference `&mut T`.
76        // mem::replace swaps the value at the location with the new `value`
77        // and returns the old value.
78        core::mem::replace(&mut self[index], value)
79    }
80
81    #[inline]
82    unsafe fn replace_value_unchecked(&mut self, index: usize, value: Self::Value) -> Self::Value {
83        // Safety: The caller must ensure that `*self` (the index) is in bounds.
84        unsafe {
85            let elem = self.get_unchecked_mut(index);
86            core::mem::replace(elem, value)
87        }
88    }
89}
90
91impl<'a, T: Clone> SliceByValueSubsliceGat<'a> for [T] {
92    type Subslice = &'a [T];
93}
94
95impl<'a, T: Clone> SliceByValueSubsliceGatMut<'a> for [T] {
96    type Subslice = &'a mut [T];
97}
98
99macro_rules! impl_range_slices {
100    ($range:ty) => {
101        impl<T: Clone> SliceByValueSubsliceRange<$range> for [T] {
102            #[inline]
103            fn get_subslice(&self, index: $range) -> Option<Subslice<'_, Self>> {
104                (*self).get(index)
105            }
106
107            #[inline]
108            fn index_subslice(&self, index: $range) -> Subslice<'_, Self> {
109                &self[index]
110            }
111
112            #[inline]
113            unsafe fn get_subslice_unchecked(&self, index: $range) -> Subslice<'_, Self> {
114                unsafe { (*self).get_unchecked(index) }
115            }
116        }
117
118        impl<T: Clone> SliceByValueSubsliceRangeMut<$range> for [T] {
119            #[inline]
120            fn get_subslice_mut(&mut self, index: $range) -> Option<SubsliceMut<'_, Self>> {
121                (*self).get_mut(index)
122            }
123
124            #[inline]
125            fn index_subslice_mut(&mut self, index: $range) -> SubsliceMut<'_, Self> {
126                &mut self[index]
127            }
128
129            #[inline]
130            unsafe fn get_subslice_unchecked_mut(
131                &mut self,
132                index: $range,
133            ) -> SubsliceMut<'_, Self> {
134                unsafe { (*self).get_unchecked_mut(index) }
135            }
136        }
137    };
138}
139
140impl_range_slices!(RangeFull);
141impl_range_slices!(RangeFrom<usize>);
142impl_range_slices!(RangeTo<usize>);
143impl_range_slices!(Range<usize>);
144impl_range_slices!(RangeInclusive<usize>);
145impl_range_slices!(RangeToInclusive<usize>);
146
147#[cfg(feature = "alloc")]
148mod alloc_impl {
149    use super::*;
150    #[cfg(all(feature = "alloc", not(feature = "std")))]
151    use alloc::boxed::Box;
152
153    impl<T: Clone> IterableByValue for Box<[T]> {
154        type Item = T;
155        type Iter<'a>
156            = Cloned<core::slice::Iter<'a, T>>
157        where
158            T: 'a;
159
160        fn iter_value(&self) -> Self::Iter<'_> {
161            self.iter().cloned()
162        }
163    }
164
165    impl<T: Clone> IterableByValueFrom for Box<[T]> {
166        type IterFrom<'a>
167            = Cloned<Skip<core::slice::Iter<'a, T>>>
168        where
169            T: 'a;
170
171        fn iter_value_from(&self, from: usize) -> Self::IterFrom<'_> {
172            self.iter().skip(from).cloned()
173        }
174    }
175}
176
177impl<T: Clone> IterableByValue for [T] {
178    type Item = T;
179    type Iter<'a>
180        = Cloned<core::slice::Iter<'a, T>>
181    where
182        T: 'a;
183
184    fn iter_value(&self) -> Self::Iter<'_> {
185        self.iter().cloned()
186    }
187}
188
189impl<T: Clone> IterableByValueFrom for [T] {
190    type IterFrom<'a>
191        = Cloned<Skip<core::slice::Iter<'a, T>>>
192    where
193        T: 'a;
194
195    fn iter_value_from(&self, from: usize) -> Self::IterFrom<'_> {
196        self.iter().skip(from).cloned()
197    }
198}