1use core::marker::PhantomData;
2use core::ops::{Bound, RangeBounds};
3
4use crate::{Slice, SliceBorrowed, SliceMut, SliceOwned, Unique};
5
6#[derive(Clone, Copy, Hash)]
8pub struct SliceOf<A> {
9 data: A,
10
11 start: Bound<usize>,
12 len: usize,
13}
14
15impl<A> SliceOf<A>
16where
17 A: Slice,
18{
19 pub fn new<R: RangeBounds<usize>>(data: A, range: R) -> Option<Self> {
21 let start = match range.start_bound().cloned() {
22 s @ Bound::Included(_) | s @ Bound::Excluded(_) => s,
23 Bound::Unbounded => Bound::Included(0),
24 };
25
26 let end = match range.end_bound().cloned() {
27 e @ Bound::Included(_) | e @ Bound::Excluded(_) => e,
28 Bound::Unbounded => Bound::Included(data.len() - 1),
29 };
30
31 match (start, end) {
37 (Bound::Included(s), Bound::Included(e)) if s > e || e >= data.len() => None,
38 (Bound::Included(s), Bound::Excluded(e)) if s > e || e > data.len() => None,
39 (Bound::Excluded(s), Bound::Included(e)) if s > e || e >= data.len() => None,
40 (Bound::Excluded(s), Bound::Excluded(e)) if s > e || e > data.len() => None,
41
42 _ => Some(Self {
43 data,
44 start,
45 len: match (start, end) {
46 (Bound::Included(s), Bound::Included(e)) => e - s + 1,
47 (Bound::Included(s), Bound::Excluded(e)) => e - s,
48 (Bound::Excluded(s), Bound::Included(e)) => e - s,
49 (Bound::Excluded(s), Bound::Excluded(e)) => e - s - 1,
50 _ => unreachable!(),
51 },
52 }),
53 }
54 }
55}
56
57impl<A> Slice for SliceOf<A>
58where
59 A: Slice,
60{
61 type Output = A::Output;
62
63 fn len(&self) -> usize {
64 self.len
65 }
66
67 fn get_with<W: FnMut(&Self::Output) -> R, R>(&self, index: usize, f: &mut W) -> Option<R> {
68 if index > self.len() {
69 None
70 } else {
71 self.data.get_with(
72 match self.start {
73 Bound::Included(s) => index + s,
74 Bound::Excluded(s) => index + s + 1,
75 _ => unreachable!(),
76 },
77 f,
78 )
79 }
80 }
81}
82
83impl<A> SliceOwned for SliceOf<A>
84where
85 A: SliceOwned,
86{
87 fn get_owned(&self, index: usize) -> Option<Self::Output> {
88 if index > self.len() {
89 None
90 } else {
91 self.data.get_owned(match self.start {
92 Bound::Included(s) => index + s,
93 Bound::Excluded(s) => index + s + 1,
94 _ => unreachable!(),
95 })
96 }
97 }
98}
99
100impl<A> SliceBorrowed for SliceOf<A>
101where
102 A: SliceBorrowed,
103{
104 fn get(&self, index: usize) -> Option<&Self::Output> {
105 if index > self.len() {
106 None
107 } else {
108 self.data.get(match self.start {
109 Bound::Included(s) => index + s,
110 Bound::Excluded(s) => index + s + 1,
111 _ => unreachable!(),
112 })
113 }
114 }
115}
116
117impl<A> SliceMut for SliceOf<A>
118where
119 A: SliceMut,
120{
121 fn get_mut(&mut self, index: usize) -> Option<&mut Self::Output> {
122 if index > self.len() {
123 None
124 } else {
125 self.data.get_mut(match self.start {
126 Bound::Included(s) => index + s,
127 Bound::Excluded(s) => index + s + 1,
128 _ => unreachable!(),
129 })
130 }
131 }
132}
133
134unsafe impl<A> Unique for SliceOf<A> where A: Unique {}
136
137#[derive(Clone, Copy, Hash)]
139pub struct SplitMut<'a, A: ?Sized> {
140 data: *mut A,
141
142 start: Bound<usize>,
143 len: usize,
144
145 _lifetime: PhantomData<&'a mut A>,
146}
147
148impl<A> SplitMut<'_, A>
149where
150 A: Slice + ?Sized,
151{
152 pub fn new(data: &mut A, at: usize) -> Option<(Self, Self)> {
154 let len = data.len();
155 if at >= len {
156 None
157 } else {
158 Some((
159 Self {
160 data: data as *mut A,
161
162 start: Bound::Included(0),
163 len: at + 1,
164
165 _lifetime: PhantomData,
166 },
167 Self {
168 data: data as *mut A,
169
170 start: Bound::Excluded(at),
171 len: len - at - 1,
172
173 _lifetime: PhantomData,
174 },
175 ))
176 }
177 }
178
179 fn data_imm(&self) -> &A {
180 unsafe { &*self.data }
182 }
183
184 fn data_mut(&mut self) -> &mut A {
185 unsafe { &mut *self.data }
187 }
188}
189
190impl<A> Slice for SplitMut<'_, A>
191where
192 A: Slice + ?Sized,
193{
194 type Output = A::Output;
195
196 fn len(&self) -> usize {
197 self.len
198 }
199
200 fn get_with<W: FnMut(&Self::Output) -> R, R>(&self, index: usize, f: &mut W) -> Option<R> {
201 if index > self.len() {
202 None
203 } else {
204 self.data_imm().get_with(
205 match self.start {
206 Bound::Included(s) => index + s,
207 Bound::Excluded(s) => index + s + 1,
208 _ => unreachable!(),
209 },
210 f,
211 )
212 }
213 }
214}
215
216impl<A> SliceBorrowed for SplitMut<'_, A>
217where
218 A: SliceBorrowed + ?Sized,
219{
220 fn get(&self, index: usize) -> Option<&Self::Output> {
221 let i = match self.start {
222 Bound::Included(s) => index + s,
223 Bound::Excluded(s) => index + s + 1,
224 _ => unreachable!(),
225 };
226
227 if index > self.len {
228 None
229 } else {
230 self.data_imm().get(i)
231 }
232 }
233}
234
235impl<A> SliceOwned for SplitMut<'_, A>
236where
237 A: SliceOwned + ?Sized,
238{
239 fn get_owned(&self, index: usize) -> Option<Self::Output> {
240 let i = match self.start {
241 Bound::Included(s) => index + s,
242 Bound::Excluded(s) => index + s + 1,
243 _ => unreachable!(),
244 };
245
246 if index > self.len {
247 None
248 } else {
249 self.data_imm().get_owned(i)
250 }
251 }
252}
253
254impl<A> SliceMut for SplitMut<'_, A>
255where
256 A: SliceMut + Unique,
257{
258 fn get_mut(&mut self, index: usize) -> Option<&mut Self::Output> {
259 let i = match self.start {
260 Bound::Included(s) => index + s,
261 Bound::Excluded(s) => index + s + 1,
262 _ => unreachable!(),
263 };
264
265 if index > self.len() {
266 None
267 } else {
268 self.data_mut().get_mut(i)
269 }
270 }
271}