1#[cfg(feature = "doc")]
2use crate::{scope, scope_ref};
3use {
4 crate::{
5 index::{Index, IndexError, Range},
6 proof::{Id, NonEmpty, Unknown},
7 traits::{Idx, TrustedContainer, TrustedItem},
8 },
9 core::{fmt, ops},
10};
11
12#[repr(transparent)]
22pub struct Container<'id, Array: TrustedContainer + ?Sized> {
23 #[allow(unused)]
24 id: Id<'id>,
25 array: Array,
26}
27
28impl<'id, Array: TrustedContainer> Container<'id, Array> {
29 pub(crate) unsafe fn new(array: Array) -> Self {
30 Container {
31 id: Id::default(),
32 array,
33 }
34 }
35}
36
37impl<'id, Array: TrustedContainer + ?Sized> Container<'id, &Array> {
38 pub fn project(&self) -> &Container<'id, Array> {
39 unsafe { &*(self.array as *const Array as *const Container<'id, Array>) }
40 }
41}
42
43impl<'id, Array: TrustedContainer + ?Sized> Container<'id, Array> {
44 pub fn untrusted(&self) -> &Array {
54 &self.array
55 }
56
57 pub fn unit_len(&self) -> usize {
59 self.array.unit_len()
60 }
61
62 pub fn start<I: Idx>(&self) -> Index<'id, I, Unknown> {
64 unsafe { Index::new(I::zero()) }
65 }
66
67 pub fn end<I: Idx>(&self) -> Index<'id, I, Unknown> {
69 let len = I::from_usize(self.unit_len()).expect("len");
70 unsafe { Index::new(len) }
71 }
72
73 pub fn empty_range<I: Idx>(&self) -> Range<'id, I, Unknown> {
75 Range::from(self.start(), self.start())
76 }
77
78 pub fn range<I: Idx>(&self) -> Range<'id, I, Unknown> {
80 Range::from(self.start(), self.end())
81 }
82
83 pub fn vet<I: Idx>(&self, idx: I) -> Result<Index<'id, I, NonEmpty>, IndexError> {
85 let item = TrustedItem::vet(idx, self)?;
87 if item < self.end() {
88 unsafe { Ok(Index::new_nonempty(item.untrusted())) }
89 } else {
90 Err(IndexError::OutOfBounds)
91 }
92 }
93
94 pub fn vet_range<I: Idx>(
97 &self,
98 r: ops::Range<I>,
99 ) -> Result<Range<'id, I, Unknown>, IndexError> {
100 Ok(Range::from(
101 TrustedItem::vet(r.start, self)?,
102 TrustedItem::vet(r.end, self)?,
103 ))
104 }
105
106 pub fn split_at<I: Idx, P>(
109 &self,
110 idx: Index<'id, I, P>,
111 ) -> (Range<'id, I, Unknown>, Range<'id, I, P>) {
112 (Range::from(self.start(), idx), unsafe {
113 Range::new_any(idx.untrusted(), self.end().untrusted())
114 })
115 }
116
117 pub fn split_after<I: Idx>(
120 &self,
121 idx: Index<'id, I, NonEmpty>,
122 ) -> (Range<'id, I, NonEmpty>, Range<'id, I, Unknown>) {
123 let mid = TrustedItem::after(idx, self);
124 (
125 unsafe { Range::new_nonempty(I::zero(), mid.untrusted()) },
126 Range::from(mid, self.end()),
127 )
128 }
129
130 pub fn split_around<I: Idx, P>(
135 &self,
136 r: Range<'id, I, P>,
137 ) -> (Range<'id, I, Unknown>, Range<'id, I, Unknown>) {
138 (
139 Range::from(self.start(), r.start()),
140 Range::from(r.end(), self.end()),
141 )
142 }
143
144 pub fn before<I: Idx, P>(&self, idx: Index<'id, I, P>) -> Range<'id, I, Unknown> {
146 Range::from(self.start(), idx)
147 }
148
149 pub fn after<I: Idx>(&self, idx: Index<'id, I, NonEmpty>) -> Range<'id, I, Unknown> {
151 let after = TrustedItem::after(idx, self);
152 Range::from(after, self.end())
153 }
154
155 pub fn advance<I: Idx>(&self, idx: Index<'id, I, NonEmpty>) -> Option<Index<'id, I, NonEmpty>> {
157 TrustedItem::advance(idx, self)
158 }
159
160 pub fn advance_by<I: Idx, P>(
163 &self,
164 idx: Index<'id, I, P>,
165 offset: usize,
166 ) -> Result<Index<'id, I, NonEmpty>, IndexError> {
167 self.vet(idx.untrusted().add(offset))
168 }
169
170 pub fn decrease_by<I: Idx, P>(
173 &self,
174 idx: Index<'id, I, P>,
175 offset: usize,
176 ) -> Result<Index<'id, I, NonEmpty>, IndexError> {
177 if idx.untrusted().as_usize() >= offset {
178 self.vet(idx.untrusted().sub(offset))
179 } else {
180 Err(IndexError::OutOfBounds)
181 }
182 }
183}
184
185impl<'id, Array: TrustedContainer + ?Sized, I: Idx> ops::Index<Index<'id, I, NonEmpty>>
186 for Container<'id, Array>
187{
188 type Output = Array::Item;
189
190 fn index(&self, index: Index<'id, I, NonEmpty>) -> &Self::Output {
191 unsafe { self.array.get_unchecked(index.untrusted().as_usize()) }
192 }
193}
194
195impl<'id, Array: TrustedContainer + ?Sized, I: Idx, P> ops::Index<Range<'id, I, P>>
196 for Container<'id, Array>
197{
198 type Output = Array::Slice;
199
200 fn index(&self, r: Range<'id, I, P>) -> &Self::Output {
201 unsafe {
202 self.array
203 .slice_unchecked(r.start().untrusted().as_usize()..r.end().untrusted().as_usize())
204 }
205 }
206}
207
208impl<'id, Array: TrustedContainer + ?Sized, I: Idx, P> ops::Index<ops::RangeFrom<Index<'id, I, P>>>
209 for Container<'id, Array>
210{
211 type Output = Array::Slice;
212
213 fn index(&self, r: ops::RangeFrom<Index<'id, I, P>>) -> &Self::Output {
214 &self[Range::from(r.start, self.end())]
215 }
216}
217
218impl<'id, Array: TrustedContainer + ?Sized, I: Idx, P> ops::Index<ops::RangeTo<Index<'id, I, P>>>
219 for Container<'id, Array>
220{
221 type Output = Array::Slice;
222
223 fn index(&self, r: ops::RangeTo<Index<'id, I, P>>) -> &Self::Output {
224 &self[Range::from(self.start(), r.end)]
225 }
226}
227
228impl<'id, Array: TrustedContainer + ?Sized> ops::Index<ops::RangeFull> for Container<'id, Array> {
229 type Output = Array::Slice;
230
231 fn index(&self, _: ops::RangeFull) -> &Self::Output {
232 &self[Range::<usize, _>::from(self.start(), self.end())]
233 }
234}
235
236impl<'id, Array: TrustedContainer + Copy> Copy for Container<'id, Array> {}
237impl<'id, Array: TrustedContainer + Clone> Clone for Container<'id, Array> {
238 fn clone(&self) -> Self {
239 unsafe { Container::new(self.array.clone()) }
240 }
241}
242
243impl<'id, Array: TrustedContainer + fmt::Debug + ?Sized> fmt::Debug for Container<'id, Array> {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 f.debug_tuple("Container<'id>").field(&&self.array).finish()
246 }
247}