blob: da04ef6fc3a489cd00515160be6d14b569e40a4a [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
2 * Copyright 2018 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
James Kuszmaul8e62b022022-03-22 09:33:25 -070017use core::fmt::{Debug, Formatter, Result};
18use core::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator};
19use core::marker::PhantomData;
20use core::mem::size_of;
21use core::slice::from_raw_parts;
22use core::str::from_utf8_unchecked;
Austin Schuhe89fa2d2019-08-14 20:24:23 -070023
Austin Schuh272c6132020-11-14 16:37:52 -080024use crate::endian_scalar::read_scalar_at;
Austin Schuhe89fa2d2019-08-14 20:24:23 -070025#[cfg(target_endian = "little")]
Austin Schuh272c6132020-11-14 16:37:52 -080026use crate::endian_scalar::EndianScalar;
27use crate::follow::Follow;
28use crate::primitives::*;
Austin Schuhe89fa2d2019-08-14 20:24:23 -070029
Austin Schuhe89fa2d2019-08-14 20:24:23 -070030pub struct Vector<'a, T: 'a>(&'a [u8], usize, PhantomData<T>);
31
James Kuszmaul8e62b022022-03-22 09:33:25 -070032impl<'a, T: 'a> Default for Vector<'a, T> {
33 fn default() -> Self {
34 // Static, length 0 vector.
35 // Note that derived default causes UB due to issues in read_scalar_at /facepalm.
36 Self(
37 &[0; core::mem::size_of::<UOffsetT>()],
38 0,
39 Default::default(),
40 )
41 }
42}
43
Austin Schuh272c6132020-11-14 16:37:52 -080044impl<'a, T> Debug for Vector<'a, T>
45where
46 T: 'a + Follow<'a>,
James Kuszmaul8e62b022022-03-22 09:33:25 -070047 <T as Follow<'a>>::Inner: Debug,
Austin Schuh272c6132020-11-14 16:37:52 -080048{
49 fn fmt(&self, f: &mut Formatter) -> Result {
50 f.debug_list().entries(self.iter()).finish()
51 }
52}
53
Austin Schuh272c6132020-11-14 16:37:52 -080054// We cannot use derive for these two impls, as it would only implement Copy
55// and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>`
56// can always be copied, no matter that `T` you have.
57impl<'a, T> Copy for Vector<'a, T> {}
58impl<'a, T> Clone for Vector<'a, T> {
59 fn clone(&self) -> Self {
60 *self
61 }
62}
63
Austin Schuhe89fa2d2019-08-14 20:24:23 -070064impl<'a, T: 'a> Vector<'a, T> {
65 #[inline(always)]
66 pub fn new(buf: &'a [u8], loc: usize) -> Self {
67 Vector {
68 0: buf,
69 1: loc,
70 2: PhantomData,
71 }
72 }
73
74 #[inline(always)]
75 pub fn len(&self) -> usize {
James Kuszmaul8e62b022022-03-22 09:33:25 -070076 unsafe { read_scalar_at::<UOffsetT>(self.0, self.1) as usize }
Austin Schuh272c6132020-11-14 16:37:52 -080077 }
78 #[inline(always)]
79 pub fn is_empty(&self) -> bool {
80 self.len() == 0
Austin Schuhe89fa2d2019-08-14 20:24:23 -070081 }
82}
83
84impl<'a, T: Follow<'a> + 'a> Vector<'a, T> {
85 #[inline(always)]
86 pub fn get(&self, idx: usize) -> T::Inner {
James Kuszmaul8e62b022022-03-22 09:33:25 -070087 assert!(idx < self.len() as usize);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070088 let sz = size_of::<T>();
89 debug_assert!(sz > 0);
90 T::follow(self.0, self.1 as usize + SIZE_UOFFSET + sz * idx)
91 }
Austin Schuh272c6132020-11-14 16:37:52 -080092
93 #[inline(always)]
94 pub fn iter(&self) -> VectorIter<'a, T> {
James Kuszmaul8e62b022022-03-22 09:33:25 -070095 VectorIter::from_vector(*self)
Austin Schuh272c6132020-11-14 16:37:52 -080096 }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070097}
98
99pub trait SafeSliceAccess {}
100impl<'a, T: SafeSliceAccess + 'a> Vector<'a, T> {
101 pub fn safe_slice(self) -> &'a [T] {
102 let buf = self.0;
103 let loc = self.1;
104 let sz = size_of::<T>();
105 debug_assert!(sz > 0);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700106 let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700107 let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
108 let ptr = data_buf.as_ptr() as *const T;
109 let s: &'a [T] = unsafe { from_raw_parts(ptr, len) };
110 s
111 }
112}
113
114impl SafeSliceAccess for u8 {}
115impl SafeSliceAccess for i8 {}
116impl SafeSliceAccess for bool {}
117
James Kuszmaul8e62b022022-03-22 09:33:25 -0700118// TODO(caspern): Get rid of this. Conditional compliation is unnecessary complexity.
119// Vectors of primitives just don't work on big endian machines!!!
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700120#[cfg(target_endian = "little")]
121mod le_safe_slice_impls {
122 impl super::SafeSliceAccess for u16 {}
123 impl super::SafeSliceAccess for u32 {}
124 impl super::SafeSliceAccess for u64 {}
125
126 impl super::SafeSliceAccess for i16 {}
127 impl super::SafeSliceAccess for i32 {}
128 impl super::SafeSliceAccess for i64 {}
129
130 impl super::SafeSliceAccess for f32 {}
131 impl super::SafeSliceAccess for f64 {}
132}
133
134#[cfg(target_endian = "little")]
135pub use self::le_safe_slice_impls::*;
136
137pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
138 let sz = size_of::<T>();
139 let buf = &buf[loc..loc + sz];
140 let ptr = buf.as_ptr() as *const T;
141 unsafe { &*ptr }
142}
143
144impl<'a> Follow<'a> for &'a str {
145 type Inner = &'a str;
146 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700147 let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) } as usize;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700148 let slice = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len];
Austin Schuh272c6132020-11-14 16:37:52 -0800149 unsafe { from_utf8_unchecked(slice) }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700150 }
151}
152
153#[cfg(target_endian = "little")]
154fn follow_slice_helper<T>(buf: &[u8], loc: usize) -> &[T] {
155 let sz = size_of::<T>();
156 debug_assert!(sz > 0);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700157 let len = unsafe { read_scalar_at::<UOffsetT>(buf, loc) as usize };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700158 let data_buf = &buf[loc + SIZE_UOFFSET..loc + SIZE_UOFFSET + len * sz];
159 let ptr = data_buf.as_ptr() as *const T;
160 let s: &[T] = unsafe { from_raw_parts(ptr, len) };
161 s
162}
163
164/// Implement direct slice access if the host is little-endian.
165#[cfg(target_endian = "little")]
166impl<'a, T: EndianScalar> Follow<'a> for &'a [T] {
167 type Inner = &'a [T];
168 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
169 follow_slice_helper::<T>(buf, loc)
170 }
171}
172
173/// Implement Follow for all possible Vectors that have Follow-able elements.
174impl<'a, T: Follow<'a> + 'a> Follow<'a> for Vector<'a, T> {
175 type Inner = Vector<'a, T>;
176 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
177 Vector::new(buf, loc)
178 }
179}
Austin Schuh272c6132020-11-14 16:37:52 -0800180
181/// An iterator over a `Vector`.
182#[derive(Debug)]
183pub struct VectorIter<'a, T: 'a> {
184 buf: &'a [u8],
185 loc: usize,
186 remaining: usize,
187 phantom: PhantomData<T>,
188}
189
190impl<'a, T: 'a> VectorIter<'a, T> {
191 #[inline]
James Kuszmaul8e62b022022-03-22 09:33:25 -0700192 pub fn from_vector(inner: Vector<'a, T>) -> Self {
Austin Schuh272c6132020-11-14 16:37:52 -0800193 VectorIter {
194 buf: inner.0,
195 // inner.1 is the location of the data for the vector.
196 // The first SIZE_UOFFSET bytes is the length. We skip
197 // that to get to the actual vector content.
198 loc: inner.1 + SIZE_UOFFSET,
199 remaining: inner.len(),
200 phantom: PhantomData,
201 }
202 }
James Kuszmaul8e62b022022-03-22 09:33:25 -0700203
204 #[inline]
205 pub fn from_slice(buf: &'a [u8], items_num: usize) -> Self {
206 VectorIter {
207 buf,
208 loc: 0,
209 remaining: items_num,
210 phantom: PhantomData,
211 }
212 }
Austin Schuh272c6132020-11-14 16:37:52 -0800213}
214
215impl<'a, T: Follow<'a> + 'a> Clone for VectorIter<'a, T> {
216 #[inline]
217 fn clone(&self) -> Self {
218 VectorIter {
219 buf: self.buf,
220 loc: self.loc,
221 remaining: self.remaining,
222 phantom: self.phantom,
223 }
224 }
225}
226
227impl<'a, T: Follow<'a> + 'a> Iterator for VectorIter<'a, T> {
228 type Item = T::Inner;
229
230 #[inline]
231 fn next(&mut self) -> Option<T::Inner> {
232 let sz = size_of::<T>();
233 debug_assert!(sz > 0);
234
235 if self.remaining == 0 {
236 None
237 } else {
238 let result = T::follow(self.buf, self.loc);
239 self.loc += sz;
240 self.remaining -= 1;
241 Some(result)
242 }
243 }
244
245 #[inline]
246 fn nth(&mut self, n: usize) -> Option<T::Inner> {
247 let sz = size_of::<T>();
248 debug_assert!(sz > 0);
249
250 self.remaining = self.remaining.saturating_sub(n);
251
252 // Note that this might overflow, but that is okay because
253 // in that case self.remaining will have been set to zero.
254 self.loc = self.loc.wrapping_add(sz * n);
255
256 self.next()
257 }
258
259 #[inline]
260 fn size_hint(&self) -> (usize, Option<usize>) {
261 (self.remaining, Some(self.remaining))
262 }
263}
264
265impl<'a, T: Follow<'a> + 'a> DoubleEndedIterator for VectorIter<'a, T> {
266 #[inline]
267 fn next_back(&mut self) -> Option<T::Inner> {
268 let sz = size_of::<T>();
269 debug_assert!(sz > 0);
270
271 if self.remaining == 0 {
272 None
273 } else {
274 self.remaining -= 1;
275 Some(T::follow(self.buf, self.loc + sz * self.remaining))
276 }
277 }
278
279 #[inline]
280 fn nth_back(&mut self, n: usize) -> Option<T::Inner> {
281 self.remaining = self.remaining.saturating_sub(n);
282 self.next_back()
283 }
284}
285
286impl<'a, T: 'a + Follow<'a>> ExactSizeIterator for VectorIter<'a, T> {
287 #[inline]
288 fn len(&self) -> usize {
289 self.remaining
290 }
291}
292
293impl<'a, T: 'a + Follow<'a>> FusedIterator for VectorIter<'a, T> {}
294
295impl<'a, T: Follow<'a> + 'a> IntoIterator for Vector<'a, T> {
296 type Item = T::Inner;
297 type IntoIter = VectorIter<'a, T>;
298 #[inline]
299 fn into_iter(self) -> Self::IntoIter {
300 self.iter()
301 }
302}
303
304impl<'a, 'b, T: Follow<'a> + 'a> IntoIterator for &'b Vector<'a, T> {
305 type Item = T::Inner;
306 type IntoIter = VectorIter<'a, T>;
307 fn into_iter(self) -> Self::IntoIter {
308 self.iter()
309 }
310}
James Kuszmaul8e62b022022-03-22 09:33:25 -0700311
312#[cfg(feature="serialize")]
313impl<'a, T> serde::ser::Serialize for Vector<'a, T>
314where
315 T: 'a + Follow<'a>,
316 <T as Follow<'a>>::Inner: serde::ser::Serialize,
317{
318 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
319 where
320 S: serde::ser::Serializer,
321 {
322 use serde::ser::SerializeSeq;
323 let mut seq = serializer.serialize_seq(Some(self.len()))?;
324 for element in self {
325 seq.serialize_element(&element)?;
326 }
327 seq.end()
328 }
329}