1use std::marker::PhantomData;
2use std::slice;
3use std::mem;
4use std::borrow::Cow;
5
6use bytemuck::Pod;
7use num_traits::{AsPrimitive, Num};
8use mzdata_param::Unit;
9
10use super::encodings::{ArrayRetrievalError, BinaryDataArrayType, Bytes};
11use super::ArrayType;
12
13
14pub trait ByteArrayView<'transient, 'lifespan: 'transient> {
15 fn view(&'lifespan self) -> Result<Cow<'lifespan, [u8]>, ArrayRetrievalError>;
16
17 fn coerce_from<T: Pod>(
18 buffer: Cow<'transient, [u8]>,
19 ) -> Result<Cow<'transient, [T]>, ArrayRetrievalError> {
20 let n = buffer.len();
21 if n == 0 {
22 return Ok(Cow::Owned(Vec::new()))
23 }
24 let z = mem::size_of::<T>();
25 if n % z != 0 {
26 return Err(ArrayRetrievalError::DataTypeSizeMismatch);
27 }
28 match buffer {
29 Cow::Borrowed(c) => {
30 Ok(Cow::Borrowed(bytemuck::try_cast_slice(c)?))
31 },
32 Cow::Owned(v) => {
33 let size_type = n / z;
34 let mut buf = Vec::with_capacity(size_type);
35 v.chunks_exact(z).try_for_each(|c| {
36 buf.extend(bytemuck::try_cast_slice(c)?);
37 Ok::<(), bytemuck::PodCastError>(())
38 })?;
39 Ok(Cow::Owned(buf))
40 },
41 }
42 }
43
44 fn coerce<T: Pod>(
45 &'lifespan self,
46 ) -> Result<Cow<'transient, [T]>, ArrayRetrievalError> {
47 match self.view() {
48 Ok(data) => {
49 #[cfg(target_endian = "big")]
50 {
51 let mut data = Cow::Owned(data.to_vec());
52 self.dtype().swap_bytes(&mut data)?;
53 Self::coerce_from(data)
54 }
55 #[cfg(not(target_endian = "big"))]
56 {
57 Self::coerce_from(data)
58 }
59 },
60 Err(err) => Err(err),
61 }
62 }
63
64 fn convert<S: Num + Clone + AsPrimitive<D> + Pod, D: Num + Clone + Copy + 'static>(
66 &'lifespan self,
67 ) -> Result<Cow<'transient, [D]>, ArrayRetrievalError> {
68 match self.coerce::<S>() {
69 Ok(view) => {
70 match view {
71 Cow::Borrowed(view) => {
72 Ok(Cow::Owned(view.iter().map(|a| a.as_()).collect()))
73 }
74 Cow::Owned(owned) => {
75 let res = owned.iter().map(|a| a.as_()).collect();
76 Ok(Cow::Owned(res))
77 }
78 }
79 }
80 Err(err) => Err(err),
81 }
82 }
83
84 fn name(&self) -> &ArrayType;
86
87 fn dtype(&self) -> BinaryDataArrayType;
89
90 fn unit(&self) -> Unit;
92
93 fn data_processing_reference(&self) -> Option<&str> {
95 None
96 }
97
98 fn to_f32(&'lifespan self) -> Result<Cow<'transient, [f32]>, ArrayRetrievalError> {
99 type D = f32;
100 match self.dtype() {
101 BinaryDataArrayType::Float32 | BinaryDataArrayType::ASCII => self.coerce::<D>(),
102 BinaryDataArrayType::Float64 => {
103 type S = f64;
104 self.convert::<S, D>()
105 }
106 BinaryDataArrayType::Int32 => {
107 type S = i32;
108 self.convert::<S, D>()
109 }
110 BinaryDataArrayType::Int64 => {
111 type S = i64;
112 self.convert::<S, D>()
113 }
114 _ => Err(ArrayRetrievalError::DataTypeSizeMismatch),
115 }
116 }
117
118 fn to_f64(&'lifespan self) -> Result<Cow<'transient, [f64]>, ArrayRetrievalError> {
119 type D = f64;
120 match self.dtype() {
121 BinaryDataArrayType::Float32 => {
122 type S = f32;
123 self.convert::<S, D>()
124 }
125 BinaryDataArrayType::Float64 | BinaryDataArrayType::ASCII => self.coerce(),
126 BinaryDataArrayType::Int32 => {
127 type S = i32;
128 self.convert::<S, D>()
129 }
130 BinaryDataArrayType::Int64 => {
131 type S = i64;
132 self.convert::<S, D>()
133 }
134 _ => Err(ArrayRetrievalError::DataTypeSizeMismatch),
135 }
136 }
137
138 fn to_i32(&'lifespan self) -> Result<Cow<'transient, [i32]>, ArrayRetrievalError> {
139 type D = i32;
140 match self.dtype() {
141 BinaryDataArrayType::Float32 => {
142 type S = f32;
143 self.convert::<S, D>()
144 }
145 BinaryDataArrayType::Float64 => {
146 type S = f64;
147 self.convert::<S, D>()
148 }
149 BinaryDataArrayType::Int32 | BinaryDataArrayType::ASCII => self.coerce::<D>(),
150 BinaryDataArrayType::Int64 => {
151 type S = i64;
152 self.convert::<S, D>()
153 }
154 _ => Err(ArrayRetrievalError::DataTypeSizeMismatch),
155 }
156 }
157
158 fn to_i64(&'lifespan self) -> Result<Cow<'transient, [i64]>, ArrayRetrievalError> {
159 type D = i64;
160 match self.dtype() {
161 BinaryDataArrayType::Float32 => {
162 type S = f32;
163 self.convert::<S, D>()
164 }
165 BinaryDataArrayType::Float64 => {
166 type S = f64;
167 self.convert::<S, D>()
168 }
169 BinaryDataArrayType::Int64 | BinaryDataArrayType::ASCII => self.coerce::<D>(),
170 BinaryDataArrayType::Int32 => {
171 type S = i32;
172 self.convert::<S, D>()
173 }
174 _ => Err(ArrayRetrievalError::DataTypeSizeMismatch),
175 }
176 }
177
178 fn data_len(&'lifespan self) -> Result<usize, ArrayRetrievalError> {
180 let view = self.view()?;
181 let n = view.len();
182 Ok(n / self.dtype().size_of())
183 }
184
185 fn iter_type<T: Pod>(&'lifespan self) -> Result<DataSliceIter<'lifespan, T>, ArrayRetrievalError> {
186 Ok(DataSliceIter::new(self.view()?))
187 }
188
189 fn iter_u8(&'lifespan self) -> Result<DataSliceIter<'lifespan, u8>, ArrayRetrievalError> {
190 Ok(DataSliceIter::new(self.view()?))
191 }
192
193 fn iter_f32(&'lifespan self) -> Result<DataSliceIter<'lifespan, f32>, ArrayRetrievalError> {
194 Ok(DataSliceIter::new(self.view()?))
195 }
196
197 fn iter_f64(&'lifespan self) -> Result<DataSliceIter<'lifespan, f64>, ArrayRetrievalError> {
198 Ok(DataSliceIter::new(self.view()?))
199 }
200
201 fn iter_i32(&'lifespan self) -> Result<DataSliceIter<'lifespan, i32>, ArrayRetrievalError> {
202 Ok(DataSliceIter::new(self.view()?))
203 }
204
205 fn iter_i64(&'lifespan self) -> Result<DataSliceIter<'lifespan, i64>, ArrayRetrievalError> {
206 Ok(DataSliceIter::new(self.view()?))
207 }
208}
209
210pub trait ByteArrayViewMut<'transient, 'lifespan: 'transient>:
211 ByteArrayView<'transient, 'lifespan>
212{
213
214 fn unit_mut(&mut self) -> &mut Unit;
216
217 fn view_mut(&'transient mut self) -> Result<&'transient mut Bytes, ArrayRetrievalError>;
221
222 fn coerce_from_mut<T: Clone + Sized>(
223 buffer: &mut [u8],
224 ) -> Result<&'transient mut [T], ArrayRetrievalError> {
225 let n = buffer.len();
226 if n == 0 {
227 return Ok(&mut [])
228 }
229 let z = mem::size_of::<T>();
230 if n % z != 0 {
231 return Err(ArrayRetrievalError::DataTypeSizeMismatch);
232 }
233 let m = n / z;
234 unsafe { Ok(slice::from_raw_parts_mut(buffer.as_mut_ptr() as *mut T, m)) }
235 }
236
237 fn coerce_mut<T: Clone + Sized>(
238 &'lifespan mut self,
239 ) -> Result<&'transient mut [T], ArrayRetrievalError> {
240 let view = self.view_mut()?;
241 #[cfg(target_endian = "big")]
242 {
243 log::error!("Mutable view of raw bytes on big endian system is only partially supported.")
244 }
245 Self::coerce_from_mut(view)
246 }
247
248 #[allow(unused)]
249 fn set_data_processing_reference(&mut self, data_processing_reference: Option<Box<str>>) {}
251}
252
253#[derive(Debug)]
254pub struct DataSliceIter<'a, T: Pod> {
255 buffer: Cow<'a, [u8]>,
256 i: usize,
257 _t: PhantomData<T>
258}
259
260impl<T: Pod> ExactSizeIterator for DataSliceIter<'_, T> {
261 fn len(&self) -> usize {
262 let z = mem::size_of::<T>();
263 self.buffer.len() / z
264 }
265}
266
267impl<'a, T: Pod> DataSliceIter<'a, T> {
268 pub fn new(buffer: Cow<'a, [u8]>) -> Self {
269 Self { buffer, i: 0, _t: PhantomData }
270 }
271
272 pub fn next_value(&mut self) -> Option<T> {
273 let z = mem::size_of::<T>();
274 let offset = z * self.i;
275 if (offset + z) > self.buffer.len() {
276 None
277 } else {
278 let data = &self.buffer[offset..offset + z];
279 #[cfg(target_endian = "big")]
280 {
281 let mut data = data.to_vec();
282 data.reverse();
283 let val = bytemuck::from_bytes(data);
284 self.i += 1;
285 Some(*val)
286 }
287 #[cfg(not(target_endian = "big"))]
288 {
289 let val = bytemuck::from_bytes(data);
290 self.i += 1;
291 Some(*val)
292 }
293 }
294 }
295}
296
297impl<T: Pod> Iterator for DataSliceIter<'_, T> {
298 type Item = T;
299
300 fn next(&mut self) -> Option<Self::Item> {
301 self.next_value()
302 }
303}