1use std::fmt::Display;
2
3use chrono::{DateTime, NaiveDate, Utc};
4
5use crate::{
6 date_time::{date_time_to_f64, date_time_to_i64, date_to_f64, date_to_i64},
7 error::Error,
8 file::{ReadAt, SubFile},
9 pqarray::read::SimpleIter,
10};
11
12use super::{
13 BoundaryValues, GenericArrays, GenericFreeformSubblocks, GenericNumbers, GenericOptionalArrays,
14 GenericScalars, NumberType,
15};
16
17#[derive(Debug, Clone, Copy, PartialEq)]
18pub enum Boundary<T: NumberType> {
19 Less(T),
20 LessEqual(T),
21}
22
23impl<T: NumberType> Boundary<T> {
24 pub fn from<U: NumberType + Into<T>>(other: Boundary<U>) -> Self {
25 match other {
26 Boundary::Less(value) => Self::Less(value.into()),
27 Boundary::LessEqual(value) => Self::LessEqual(value.into()),
28 }
29 }
30
31 pub fn from_value(value: T, is_inclusive: bool) -> Self {
32 if is_inclusive {
33 Self::LessEqual(value)
34 } else {
35 Self::Less(value)
36 }
37 }
38
39 pub fn value(self) -> T {
40 match self {
41 Boundary::Less(value) | Boundary::LessEqual(value) => value,
42 }
43 }
44
45 pub fn is_inclusive(self) -> bool {
46 match self {
47 Boundary::Less(_) => false,
48 Boundary::LessEqual(_) => true,
49 }
50 }
51
52 pub fn map<U: NumberType>(self, func: impl FnOnce(T) -> U) -> Boundary<U> {
53 match self {
54 Boundary::Less(t) => Boundary::Less(func(t)),
55 Boundary::LessEqual(t) => Boundary::LessEqual(func(t)),
56 }
57 }
58}
59
60impl<T: NumberType + Display> Display for Boundary<T> {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 match self {
63 Self::Less(value) => write!(f, "< {value}"),
64 Self::LessEqual(value) => write!(f, "≤ {value}"),
65 }
66 }
67}
68
69#[derive(Debug)]
73pub enum Scalars<R: ReadAt> {
74 F32(GenericScalars<f32, R>),
75 F64(GenericScalars<f64, R>),
76}
77
78impl<R: ReadAt> Iterator for Scalars<R> {
79 type Item = Result<f64, Error>;
80
81 fn next(&mut self) -> Option<Self::Item> {
82 match self {
83 Self::F64(iter) => iter.next(),
84 Self::F32(iter) => iter.next().map(|r| r.map(Into::into)),
85 }
86 }
87}
88
89#[derive(Debug)]
93pub enum Vertices<R: ReadAt> {
94 F32(GenericArrays<f32, 3, R>),
95 F64(GenericArrays<f64, 3, R>),
96}
97
98impl<R: ReadAt> Iterator for Vertices<R> {
99 type Item = Result<[f64; 3], Error>;
100
101 fn next(&mut self) -> Option<Self::Item> {
102 match self {
103 Self::F64(iter) => iter.next(),
104 Self::F32(iter) => array_item_cast(iter.next()),
105 }
106 }
107}
108
109fn array_item_cast<T, U: From<T>, const N: usize>(
110 input: Option<Result<[T; N], Error>>,
111) -> Option<Result<[U; N], Error>> {
112 input.map(|r| r.map(|a| a.map(Into::into)))
113}
114
115#[derive(Debug)]
119pub enum Texcoords<R: ReadAt> {
120 F32(GenericArrays<f32, 2, R>),
121 F64(GenericArrays<f64, 2, R>),
122}
123
124impl<R: ReadAt> Iterator for Texcoords<R> {
125 type Item = Result<[f64; 2], Error>;
126
127 fn next(&mut self) -> Option<Self::Item> {
128 match self {
129 Self::F64(iter) => iter.next(),
130 Self::F32(iter) => array_item_cast(iter.next()),
131 }
132 }
133}
134
135#[derive(Debug)]
140pub enum Numbers<R: ReadAt> {
141 F32(GenericNumbers<f32, R>),
142 F64(GenericNumbers<f64, R>),
143 I64(GenericNumbers<i64, R>),
144 Date(GenericNumbers<NaiveDate, R>),
145 DateTime(GenericNumbers<DateTime<Utc>, R>),
146}
147
148impl<R: ReadAt> Numbers<R> {
149 pub fn try_into_f64(self) -> Result<NumbersF64<R>, Error> {
157 match &self {
158 Numbers::I64(_) => Err(Error::UnsafeCast("64-bit integer", "64-bit float")),
159 Numbers::F32(_) | Numbers::F64(_) | Numbers::Date(_) | Numbers::DateTime(_) => {
160 Ok(NumbersF64(self))
161 }
162 }
163 }
164
165 pub fn try_into_i64(self) -> Result<NumbersI64<R>, Error> {
171 match self {
172 Numbers::F32(_) => Err(Error::UnsafeCast("32-bit float", "64-bit integer")),
173 Numbers::F64(_) => Err(Error::UnsafeCast("64-bit float", "64-bit integer")),
174 Numbers::I64(_) | Numbers::Date(_) | Numbers::DateTime(_) => Ok(NumbersI64(self)),
175 }
176 }
177}
178
179pub struct NumbersF64<R: ReadAt>(Numbers<R>);
180
181impl<R: ReadAt> Iterator for NumbersF64<R> {
182 type Item = Result<Option<f64>, Error>;
183
184 fn next(&mut self) -> Option<Self::Item> {
185 match &mut self.0 {
186 Numbers::F32(i) => i.next().map(|r| r.map(|o| o.map(Into::into))),
187 Numbers::F64(i) => i.next(),
188 Numbers::Date(i) => i.next().map(|r| r.map(|o| o.map(date_to_f64))),
189 Numbers::DateTime(i) => i.next().map(|r| r.map(|o| o.map(date_time_to_f64))),
190 Numbers::I64(_) => None,
191 }
192 }
193}
194
195pub struct NumbersI64<R: ReadAt>(Numbers<R>);
196
197impl<R: ReadAt> Iterator for NumbersI64<R> {
198 type Item = Result<Option<i64>, Error>;
199
200 fn next(&mut self) -> Option<Self::Item> {
201 match &mut self.0 {
202 Numbers::F32(_) | Numbers::F64(_) => None,
203 Numbers::I64(i) => i.next(),
204 Numbers::Date(i) => i.next().map(|r| r.map(|o| o.map(date_to_i64))),
205 Numbers::DateTime(i) => i.next().map(|r| r.map(|o| o.map(date_time_to_i64))),
206 }
207 }
208}
209
210#[derive(Debug)]
215pub enum Vectors<R: ReadAt> {
216 F32x2(GenericOptionalArrays<f32, 2, R>),
217 F64x2(GenericOptionalArrays<f64, 2, R>),
218 F32x3(GenericOptionalArrays<f32, 3, R>),
219 F64x3(GenericOptionalArrays<f64, 3, R>),
220}
221
222impl<R: ReadAt> Iterator for Vectors<R> {
223 type Item = Result<Option<[f64; 3]>, Error>;
224
225 fn next(&mut self) -> Option<Self::Item> {
226 match self {
227 Self::F32x2(iter) => iter
228 .next()
229 .map(|r| r.map(|o| o.map(|[x, y]| [x.into(), y.into(), 0.0]))),
230 Self::F64x2(iter) => iter.next().map(|r| r.map(|o| o.map(|[x, y]| [x, y, 0.0]))),
231 Self::F32x3(iter) => {
232 let input = iter.next();
233 input.map(|r| r.map(|o| o.map(|a| a.map(Into::into))))
234 }
235 Self::F64x3(iter) => iter.next(),
236 }
237 }
238}
239
240pub struct GenericBoundaries<T: NumberType, R: ReadAt> {
242 value: BoundaryValues<T, R>,
243 inclusive: SimpleIter<bool, SubFile<R>>,
244}
245
246impl<T: NumberType + std::fmt::Debug, R: ReadAt + std::fmt::Debug> std::fmt::Debug
247 for GenericBoundaries<T, R>
248{
249 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
250 f.debug_struct("GenericBoundaries")
251 .field("value", &self.value)
252 .field("inclusive", &"...")
253 .finish()
254 }
255}
256
257impl<T: NumberType, R: ReadAt> GenericBoundaries<T, R> {
258 pub fn new(value: SimpleIter<T, SubFile<R>>, inclusive: SimpleIter<bool, SubFile<R>>) -> Self {
259 Self {
260 value: BoundaryValues::new(value),
261 inclusive,
262 }
263 }
264}
265
266impl<T: NumberType, R: ReadAt> Iterator for GenericBoundaries<T, R> {
267 type Item = Result<Boundary<T>, Error>;
268
269 fn next(&mut self) -> Option<Self::Item> {
270 match (self.value.next(), self.inclusive.next()) {
271 (Some(Err(e)), _) | (_, Some(Err(e))) => Some(Err(e)),
272 (None, _) | (_, None) => None,
273 (Some(Ok(value)), Some(Ok(false))) => Some(Ok(Boundary::Less(value))),
274 (Some(Ok(value)), Some(Ok(true))) => Some(Ok(Boundary::LessEqual(value))),
275 }
276 }
277}
278
279#[derive(Debug)]
283pub enum Boundaries<R: ReadAt> {
284 F32(GenericBoundaries<f32, R>),
285 F64(GenericBoundaries<f64, R>),
286 I64(GenericBoundaries<i64, R>),
287 Date(GenericBoundaries<NaiveDate, R>),
288 DateTime(GenericBoundaries<DateTime<Utc>, R>),
289}
290
291impl<R: ReadAt> Boundaries<R> {
292 pub fn try_into_f64(self) -> Result<BoundariesF64<R>, Error> {
300 match &self {
301 Boundaries::I64(_) => Err(Error::UnsafeCast("64-bit integer", "64-bit float")),
302 Boundaries::F32(_)
303 | Boundaries::F64(_)
304 | Boundaries::Date(_)
305 | Boundaries::DateTime(_) => Ok(BoundariesF64(self)),
306 }
307 }
308
309 pub fn try_into_i64(self) -> Result<BoundariesI64<R>, Error> {
315 match self {
316 Boundaries::F32(_) => Err(Error::UnsafeCast("32-bit float", "64-bit integer")),
317 Boundaries::F64(_) => Err(Error::UnsafeCast("64-bit float", "64-bit integer")),
318 Boundaries::I64(_) | Boundaries::Date(_) | Boundaries::DateTime(_) => {
319 Ok(BoundariesI64(self))
320 }
321 }
322 }
323}
324
325pub struct BoundariesF64<R: ReadAt>(Boundaries<R>);
326
327impl<R: ReadAt> Iterator for BoundariesF64<R> {
328 type Item = Result<Boundary<f64>, Error>;
329
330 fn next(&mut self) -> Option<Self::Item> {
331 match &mut self.0 {
332 Boundaries::F32(i) => i.next().map(|r| r.map(|o| o.map(Into::into))),
333 Boundaries::F64(i) => i.next(),
334 Boundaries::Date(i) => i.next().map(|r| r.map(|o| o.map(date_to_f64))),
335 Boundaries::DateTime(i) => i.next().map(|r| r.map(|o| o.map(date_time_to_f64))),
336 Boundaries::I64(_) => None,
337 }
338 }
339}
340
341pub struct BoundariesI64<R: ReadAt>(Boundaries<R>);
342
343impl<R: ReadAt> Iterator for BoundariesI64<R> {
344 type Item = Result<Boundary<i64>, Error>;
345
346 fn next(&mut self) -> Option<Self::Item> {
347 match &mut self.0 {
348 Boundaries::F32(_) | Boundaries::F64(_) => None,
349 Boundaries::I64(i) => i.next(),
350 Boundaries::Date(i) => i.next().map(|r| r.map(|o| o.map(date_to_i64))),
351 Boundaries::DateTime(i) => i.next().map(|r| r.map(|o| o.map(date_time_to_i64))),
352 }
353 }
354}
355
356#[derive(Debug)]
361pub enum FreeformSubblocks<R: ReadAt> {
362 F32(GenericFreeformSubblocks<f32, R>),
363 F64(GenericFreeformSubblocks<f64, R>),
364}
365
366impl<R: ReadAt> Iterator for FreeformSubblocks<R> {
367 type Item = Result<([u32; 3], [f64; 6]), Error>;
368
369 fn next(&mut self) -> Option<Self::Item> {
370 match self {
371 Self::F64(iter) => iter.next(),
372 Self::F32(iter) => match iter.next() {
373 Some(Ok((parent, corners))) => Some(Ok((parent, corners.map(Into::into)))),
374 Some(Err(e)) => Some(Err(e)),
375 None => None,
376 },
377 }
378 }
379}