• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 
17 use crate::follow::Follow;
18 use crate::vector::VectorIter;
19 use crate::EndianScalar;
20 use core::fmt::{Debug, Formatter, Result};
21 use core::marker::PhantomData;
22 use core::mem::size_of;
23 
24 #[derive(Copy, Clone)]
25 pub struct Array<'a, T: 'a, const N: usize>(&'a [u8], PhantomData<T>);
26 
27 impl<'a, T: 'a, const N: usize> Debug for Array<'a, T, N>
28 where
29     T: 'a + Follow<'a>,
30     <T as Follow<'a>>::Inner: Debug,
31 {
fmt(&self, f: &mut Formatter) -> Result32     fn fmt(&self, f: &mut Formatter) -> Result {
33         f.debug_list().entries(self.iter()).finish()
34     }
35 }
36 
37 #[allow(clippy::len_without_is_empty)]
38 #[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into.
39 impl<'a, T: 'a, const N: usize> Array<'a, T, N> {
40     /// # Safety
41     ///
42     /// buf must be a contiguous array of `T`
43     ///
44     /// # Panics
45     ///
46     /// Panics if `buf.len()` is not `size_of::<T>() * N`
47     #[inline(always)]
new(buf: &'a [u8]) -> Self48     pub unsafe fn new(buf: &'a [u8]) -> Self {
49         assert_eq!(size_of::<T>() * N, buf.len());
50 
51         Array(buf, PhantomData)
52     }
53 
54     #[inline(always)]
len(&self) -> usize55     pub const fn len(&self) -> usize {
56         N
57     }
as_ptr(&self) -> *const u858     pub fn as_ptr(&self) -> *const u8 {
59         self.0.as_ptr()
60     }
61 }
62 
63 impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> {
64     #[inline(always)]
get(&self, idx: usize) -> T::Inner65     pub fn get(&self, idx: usize) -> T::Inner {
66         assert!(idx < N);
67         let sz = size_of::<T>();
68         // Safety:
69         // self.0 was valid for length `N` on construction and have verified `idx < N`
70         unsafe { T::follow(self.0, sz * idx) }
71     }
72 
73     #[inline(always)]
iter(&self) -> VectorIter<'a, T>74     pub fn iter(&self) -> VectorIter<'a, T> {
75         // Safety:
76         // self.0 was valid for length N on construction
77         unsafe { VectorIter::from_slice(self.0, self.len()) }
78     }
79 }
80 
81 impl<'a, T: Follow<'a> + Debug, const N: usize> From<Array<'a, T, N>> for [T::Inner; N] {
from(array: Array<'a, T, N>) -> Self82     fn from(array: Array<'a, T, N>) -> Self {
83         array_init(|i| array.get(i))
84     }
85 }
86 
87 /// Implement Follow for all possible Arrays that have Follow-able elements.
88 impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> {
89     type Inner = Array<'a, T, N>;
90     #[inline(always)]
follow(buf: &'a [u8], loc: usize) -> Self::Inner91     unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
92         Array::new(&buf[loc..loc + N * size_of::<T>()])
93     }
94 }
95 
96 /// Place an array of EndianScalar into the provided mutable byte slice. Performs
97 /// endian conversion, if necessary.
98 /// # Safety
99 /// Caller must ensure `s.len() >= size_of::<[T; N]>()`
emplace_scalar_array<T: EndianScalar, const N: usize>( buf: &mut [u8], loc: usize, src: &[T; N], )100 pub unsafe fn emplace_scalar_array<T: EndianScalar, const N: usize>(
101     buf: &mut [u8],
102     loc: usize,
103     src: &[T; N],
104 ) {
105     let mut buf_ptr = buf[loc..].as_mut_ptr();
106     for item in src.iter() {
107         let item_le = item.to_little_endian();
108         core::ptr::copy_nonoverlapping(
109             &item_le as *const T::Scalar as *const u8,
110             buf_ptr,
111             size_of::<T::Scalar>(),
112         );
113         buf_ptr = buf_ptr.add(size_of::<T::Scalar>());
114     }
115 }
116 
117 impl<'a, T: Follow<'a> + 'a, const N: usize> IntoIterator for Array<'a, T, N> {
118     type Item = T::Inner;
119     type IntoIter = VectorIter<'a, T>;
120     #[inline]
into_iter(self) -> Self::IntoIter121     fn into_iter(self) -> Self::IntoIter {
122         self.iter()
123     }
124 }
125 
126 #[inline]
array_init<F, T, const N: usize>(mut initializer: F) -> [T; N] where F: FnMut(usize) -> T,127 pub fn array_init<F, T, const N: usize>(mut initializer: F) -> [T; N]
128 where
129     F: FnMut(usize) -> T,
130 {
131     let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
132     let mut ptr_i = array.as_mut_ptr() as *mut T;
133 
134     // Safety:
135     // array is aligned by T, and has length N
136     unsafe {
137         for i in 0..N {
138             let value_i = initializer(i);
139             ptr_i.write(value_i);
140             ptr_i = ptr_i.add(1);
141         }
142         array.assume_init()
143     }
144 }
145 
146 #[cfg(feature = "serialize")]
147 impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N>
148 where
149     T: 'a + Follow<'a>,
150     <T as Follow<'a>>::Inner: serde::ser::Serialize,
151 {
serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> where S: serde::ser::Serializer,152     fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
153     where
154         S: serde::ser::Serializer,
155     {
156         use serde::ser::SerializeSeq;
157         let mut seq = serializer.serialize_seq(Some(self.len()))?;
158         for element in self.iter() {
159             seq.serialize_element(&element)?;
160         }
161         seq.end()
162     }
163 }
164