/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flatbuffers-25.2.10/src/array.rs
Line | Count | Source |
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 | | { |
32 | 0 | fn fmt(&self, f: &mut Formatter) -> Result { |
33 | 0 | f.debug_list().entries(self.iter()).finish() |
34 | 0 | } |
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)] |
48 | 0 | pub unsafe fn new(buf: &'a [u8]) -> Self { |
49 | 0 | assert_eq!(size_of::<T>() * N, buf.len()); |
50 | | |
51 | 0 | Array(buf, PhantomData) |
52 | 0 | } |
53 | | |
54 | | #[inline(always)] |
55 | 0 | pub const fn len(&self) -> usize { |
56 | 0 | N |
57 | 0 | } |
58 | 0 | pub fn as_ptr(&self) -> *const u8 { |
59 | 0 | self.0.as_ptr() |
60 | 0 | } |
61 | | } |
62 | | |
63 | | impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> { |
64 | | #[inline(always)] |
65 | 0 | pub fn get(&self, idx: usize) -> T::Inner { |
66 | 0 | assert!(idx < N); |
67 | 0 | let sz = size_of::<T>(); |
68 | | // Safety: |
69 | | // self.0 was valid for length `N` on construction and have verified `idx < N` |
70 | 0 | unsafe { T::follow(self.0, sz * idx) } |
71 | 0 | } |
72 | | |
73 | | #[inline(always)] |
74 | 0 | pub fn iter(&self) -> VectorIter<'a, T> { |
75 | | // Safety: |
76 | | // self.0 was valid for length N on construction |
77 | 0 | unsafe { VectorIter::from_slice(self.0, self.len()) } |
78 | 0 | } |
79 | | } |
80 | | |
81 | | impl<'a, T: Follow<'a> + Debug, const N: usize> From<Array<'a, T, N>> for [T::Inner; N] { |
82 | 0 | fn from(array: Array<'a, T, N>) -> Self { |
83 | 0 | array_init(|i| array.get(i)) |
84 | 0 | } |
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)] |
91 | 0 | unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { |
92 | 0 | Array::new(&buf[loc..loc + N * size_of::<T>()]) |
93 | 0 | } |
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]>()` |
100 | 0 | pub unsafe fn emplace_scalar_array<T: EndianScalar, const N: usize>( |
101 | 0 | buf: &mut [u8], |
102 | 0 | loc: usize, |
103 | 0 | src: &[T; N], |
104 | 0 | ) { |
105 | 0 | let mut buf_ptr = buf[loc..].as_mut_ptr(); |
106 | 0 | for item in src.iter() { |
107 | 0 | let item_le = item.to_little_endian(); |
108 | 0 | core::ptr::copy_nonoverlapping( |
109 | 0 | &item_le as *const T::Scalar as *const u8, |
110 | 0 | buf_ptr, |
111 | 0 | size_of::<T::Scalar>(), |
112 | 0 | ); |
113 | 0 | buf_ptr = buf_ptr.add(size_of::<T::Scalar>()); |
114 | 0 | } |
115 | 0 | } |
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] |
121 | 0 | fn into_iter(self) -> Self::IntoIter { |
122 | 0 | self.iter() |
123 | 0 | } |
124 | | } |
125 | | |
126 | | #[inline] |
127 | 0 | pub fn array_init<F, T, const N: usize>(mut initializer: F) -> [T; N] |
128 | 0 | where |
129 | 0 | F: FnMut(usize) -> T, |
130 | | { |
131 | 0 | let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit(); |
132 | 0 | 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 | 0 | for i in 0..N { |
138 | 0 | let value_i = initializer(i); |
139 | 0 | ptr_i.write(value_i); |
140 | 0 | ptr_i = ptr_i.add(1); |
141 | 0 | } |
142 | 0 | array.assume_init() |
143 | | } |
144 | 0 | } |
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 | | { |
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 | | } |