• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 13006212569

28 Jan 2025 08:16AM UTC coverage: 90.028% (-0.07%) from 90.097%
13006212569

Pull #1011

github

web-flow
Merge e1b432aa2 into ef1edce10
Pull Request #1011: update to rust 1.84

46 of 54 new or added lines in 14 files covered. (85.19%)

103 existing lines in 42 files now uncovered.

125589 of 139500 relevant lines covered (90.03%)

57700.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.63
/datatypes/src/primitives/feature_data.rs
1
use crate::error;
2
use crate::primitives::TimeInstance;
3
use crate::raster::RasterDataType;
4
use crate::util::helpers::indices_for_split_at;
5
use crate::util::Result;
6
use arrow::buffer::NullBuffer;
7
use arrow_array::{BooleanArray, Date64Array, Float64Array, Int64Array, StringArray};
8
use gdal::vector::OGRFieldType;
9
use num_traits::AsPrimitive;
10
use postgres_types::{FromSql, ToSql};
11
use rayon::iter::plumbing::Producer;
12
use rayon::iter::{IndexedParallelIterator, ParallelIterator};
13
use serde::{Deserialize, Serialize};
14
use serde_json::Value;
15
use snafu::ensure;
16
use std::convert::TryFrom;
17
use std::str;
18
use std::{marker::PhantomData, slice};
19

UNCOV
20
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize, FromSql, ToSql)]
×
21
#[serde(rename_all = "camelCase")]
22
pub enum FeatureDataType {
23
    Category,
24
    Int,
25
    Float,
26
    Text,
27
    Bool,
28
    DateTime,
29
}
30

31
impl FeatureDataType {
32
    pub fn try_from_ogr_field_type_code(code: u32) -> Result<Self> {
×
33
        Ok(match code {
×
34
            OGRFieldType::OFTInteger | OGRFieldType::OFTInteger64 => Self::Int,
×
35
            OGRFieldType::OFTReal => Self::Float,
×
36
            OGRFieldType::OFTString => Self::Text,
×
37
            OGRFieldType::OFTBinary => Self::Bool,
×
38
            OGRFieldType::OFTDateTime | OGRFieldType::OFTDate => Self::DateTime,
×
39
            _ => return Err(error::Error::NoMatchingFeatureDataTypeForOgrFieldType),
×
40
        })
41
    }
×
42

43
    pub fn is_numeric(self) -> bool {
32✔
44
        matches!(self, Self::Int | Self::Float)
32✔
45
    }
32✔
46
}
47

48
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
49
pub enum FeatureData {
50
    Category(Vec<u8>), // TODO: add names to categories
51
    NullableCategory(Vec<Option<u8>>),
52
    Int(Vec<i64>),
53
    NullableInt(Vec<Option<i64>>),
54
    Float(Vec<f64>),
55
    NullableFloat(Vec<Option<f64>>),
56
    Text(Vec<String>),
57
    NullableText(Vec<Option<String>>),
58
    Bool(Vec<bool>),
59
    NullableBool(Vec<Option<bool>>),
60
    DateTime(Vec<TimeInstance>),
61
    NullableDateTime(Vec<Option<TimeInstance>>),
62
}
63

64
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
65
pub enum FeatureDataValue {
66
    Category(u8),
67
    NullableCategory(Option<u8>),
68
    Int(i64),
69
    NullableInt(Option<i64>),
70
    Float(f64),
71
    NullableFloat(Option<f64>),
72
    Text(String),
73
    NullableText(Option<String>),
74
    Bool(bool),
75
    NullableBool(Option<bool>),
76
    DateTime(TimeInstance),
77
    NullableDateTime(Option<TimeInstance>),
78
}
79

80
#[derive(Clone, Debug, PartialEq)]
81
pub enum FeatureDataRef<'f> {
82
    Category(CategoryDataRef<'f>),
83
    Int(IntDataRef<'f>),
84
    Float(FloatDataRef<'f>),
85
    Text(TextDataRef<'f>),
86
    Bool(BoolDataRef<'f>),
87
    DateTime(DateTimeDataRef<'f>),
88
}
89

90
impl FeatureDataRef<'_> {
91
    /// Computes JSON value lists for data elements
92
    pub fn json_values(&self) -> Box<dyn Iterator<Item = serde_json::Value> + '_> {
4✔
93
        match self {
4✔
94
            FeatureDataRef::Text(data_ref) => data_ref.json_values(),
1✔
95
            FeatureDataRef::Float(data_ref) => data_ref.json_values(),
1✔
96
            FeatureDataRef::Int(data_ref) => data_ref.json_values(),
2✔
97
            FeatureDataRef::Category(data_ref) => data_ref.json_values(),
×
98
            FeatureDataRef::Bool(data_ref) => data_ref.json_values(),
×
99
            FeatureDataRef::DateTime(data_ref) => data_ref.json_values(),
×
100
        }
101
    }
4✔
102

103
    /// Computes a vector of null flags.
104
    pub fn nulls(&self) -> Vec<bool> {
1✔
105
        match self {
1✔
106
            FeatureDataRef::Text(data_ref) => data_ref.nulls(),
1✔
107
            FeatureDataRef::Float(data_ref) => data_ref.nulls(),
×
108
            FeatureDataRef::Int(data_ref) => data_ref.nulls(),
×
109
            FeatureDataRef::Category(data_ref) => data_ref.nulls(),
×
110
            FeatureDataRef::Bool(data_ref) => data_ref.nulls(),
×
111
            FeatureDataRef::DateTime(data_ref) => data_ref.nulls(),
×
112
        }
113
    }
1✔
114

115
    /// Is any of the data elements null?
116
    pub fn has_nulls(&self) -> bool {
4✔
117
        match self {
4✔
118
            FeatureDataRef::Text(data_ref) => data_ref.has_nulls(),
2✔
119
            FeatureDataRef::Float(data_ref) => data_ref.has_nulls(),
×
120
            FeatureDataRef::Int(data_ref) => data_ref.has_nulls(),
2✔
121
            FeatureDataRef::Category(data_ref) => data_ref.has_nulls(),
×
122
            FeatureDataRef::Bool(data_ref) => data_ref.has_nulls(),
×
123
            FeatureDataRef::DateTime(data_ref) => data_ref.has_nulls(),
×
124
        }
125
    }
4✔
126

127
    /// Get the `FeatureDataValue` value at position `i`
128
    pub fn get_unchecked(&self, i: usize) -> FeatureDataValue {
65✔
129
        match self {
65✔
130
            FeatureDataRef::Text(data_ref) => data_ref.get_unchecked(i),
25✔
131
            FeatureDataRef::Float(data_ref) => data_ref.get_unchecked(i),
10✔
132
            FeatureDataRef::Int(data_ref) => data_ref.get_unchecked(i),
30✔
133
            FeatureDataRef::Category(data_ref) => data_ref.get_unchecked(i),
×
134
            FeatureDataRef::Bool(data_ref) => data_ref.get_unchecked(i),
×
135
            FeatureDataRef::DateTime(data_ref) => data_ref.get_unchecked(i),
×
136
        }
137
    }
65✔
138

139
    /// Creates an iterator over all values as string
140
    /// Null-values are empty strings.
141
    pub fn strings_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
56✔
142
        match self {
56✔
143
            FeatureDataRef::Text(data_ref) => Box::new(data_ref.strings_iter()),
51✔
144
            FeatureDataRef::Float(data_ref) => Box::new(data_ref.strings_iter()),
2✔
145
            FeatureDataRef::Int(data_ref) => Box::new(data_ref.strings_iter()),
1✔
146
            FeatureDataRef::Category(data_ref) => Box::new(data_ref.strings_iter()),
×
147
            FeatureDataRef::Bool(data_ref) => Box::new(data_ref.strings_iter()),
1✔
148
            FeatureDataRef::DateTime(data_ref) => Box::new(data_ref.strings_iter()),
1✔
149
        }
150
    }
56✔
151

152
    /// Creates an iterator over all values as [`Option<f64>`]
153
    /// Null values or non-convertible values are [`None`]
154
    pub fn float_options_iter(&self) -> FloatOptionsIter {
75✔
155
        match self {
75✔
156
            FeatureDataRef::Text(data_ref) => FloatOptionsIter::Text(data_ref.float_options_iter()),
4✔
157
            FeatureDataRef::Float(data_ref) => {
29✔
158
                FloatOptionsIter::Float(data_ref.float_options_iter())
29✔
159
            }
160
            FeatureDataRef::Int(data_ref) => FloatOptionsIter::Int(data_ref.float_options_iter()),
30✔
161
            FeatureDataRef::Category(data_ref) => {
4✔
162
                FloatOptionsIter::Category(data_ref.float_options_iter())
4✔
163
            }
164
            FeatureDataRef::Bool(data_ref) => FloatOptionsIter::Bool(data_ref.float_options_iter()),
4✔
165
            FeatureDataRef::DateTime(data_ref) => {
4✔
166
                FloatOptionsIter::DateTime(data_ref.float_options_iter())
4✔
167
            }
168
        }
169
    }
75✔
170

171
    /// Creates a parallel iterator over all values as [`Option<f64>`]
172
    /// Null values or non-convertible values are [`None`]
173
    pub fn float_options_par_iter(&self) -> FloatOptionsParIter {
17✔
174
        self.float_options_iter().into()
17✔
175
    }
17✔
176
}
177

178
/// Common methods for feature data references
179
pub trait DataRef<'r, T>: AsRef<[T]> + Into<FeatureDataRef<'r>>
180
where
181
    T: 'static,
182
{
183
    type StringsIter: Iterator<Item = String>;
184
    type FloatOptionsIter: Iterator<Item = Option<f64>>
185
        + IndexedParallelIterator<Item = Option<f64>>;
186

187
    /// Computes JSON value lists for data elements
188
    fn json_values(&'r self) -> Box<dyn Iterator<Item = serde_json::Value> + 'r> {
3✔
189
        if self.has_nulls() {
3✔
190
            Box::new(self.as_ref().iter().enumerate().map(move |(i, v)| {
5✔
191
                if self.is_null(i) {
5✔
192
                    serde_json::Value::Null
1✔
193
                } else {
194
                    Self::json_value(v)
4✔
195
                }
196
            }))
5✔
197
        } else {
198
            Box::new(self.as_ref().iter().map(Self::json_value))
2✔
199
        }
200
    }
3✔
201

202
    /// Creates a JSON value out of the owned type
203
    fn json_value(value: &T) -> serde_json::Value;
204

205
    /// Computes a vector of null flags.
206
    fn nulls(&self) -> Vec<bool>;
207

208
    /// Is the `i`th value null?
209
    /// This method panics if `i` is too large.
210
    fn is_null(&self, i: usize) -> bool {
58,449✔
211
        !self.is_valid(i)
58,449✔
212
    }
58,449✔
213

214
    /// Is the `i`th value valid, i.e., not null?
215
    /// This method panics if `i` is too large.
216
    fn is_valid(&self, i: usize) -> bool;
217

218
    /// Is any of the data elements null?
219
    fn has_nulls(&self) -> bool;
220

221
    fn get_unchecked(&self, i: usize) -> FeatureDataValue;
222

223
    /// Number of values
224
    fn len(&self) -> usize;
225

226
    fn is_empty(&self) -> bool {
×
227
        self.len() == 0
×
228
    }
×
229

230
    /// Creates an iterator over all values as string
231
    /// Null values are empty strings.
232
    fn strings_iter(&'r self) -> Self::StringsIter;
233

234
    /// Creates an iterator over all values as [`Option<f64>`]
235
    /// Null values or non-convertible values are [`None`]
236
    fn float_options_iter(&'r self) -> Self::FloatOptionsIter;
237
}
238

239
#[derive(Debug, Clone)]
240
pub enum FloatOptionsIter<'f> {
241
    Category(<CategoryDataRef<'f> as DataRef<'f, u8>>::FloatOptionsIter),
242
    Int(<IntDataRef<'f> as DataRef<'f, i64>>::FloatOptionsIter),
243
    Float(<FloatDataRef<'f> as DataRef<'f, f64>>::FloatOptionsIter),
244
    Text(<TextDataRef<'f> as DataRef<'f, u8>>::FloatOptionsIter),
245
    Bool(<BoolDataRef<'f> as DataRef<'f, bool>>::FloatOptionsIter),
246
    DateTime(<DateTimeDataRef<'f> as DataRef<'f, TimeInstance>>::FloatOptionsIter),
247
}
248

249
#[derive(Debug, Clone)]
250
pub struct FloatOptionsParIter<'f>(FloatOptionsIter<'f>);
251

252
impl<'f> From<FloatOptionsIter<'f>> for FloatOptionsParIter<'f> {
253
    fn from(iter: FloatOptionsIter<'f>) -> Self {
93✔
254
        Self(iter)
93✔
255
    }
93✔
256
}
257

258
impl Iterator for FloatOptionsIter<'_> {
259
    type Item = Option<f64>;
260

261
    fn next(&mut self) -> Option<Self::Item> {
58,476✔
262
        match self {
58,476✔
263
            Self::Category(iter) => iter.next(),
16✔
264
            Self::Int(iter) => iter.next(),
57,495✔
265
            Self::Float(iter) => iter.next(),
917✔
266
            Self::Text(iter) => iter.next(),
16✔
267
            Self::Bool(iter) => iter.next(),
16✔
268
            Self::DateTime(iter) => iter.next(),
16✔
269
        }
270
    }
58,476✔
271

272
    fn size_hint(&self) -> (usize, Option<usize>) {
82✔
273
        match self {
82✔
274
            Self::Category(iter) => iter.size_hint(),
10✔
275
            Self::Int(iter) => iter.size_hint(),
12✔
276
            Self::Float(iter) => iter.size_hint(),
30✔
277
            Self::Text(iter) => iter.size_hint(),
10✔
278
            Self::Bool(iter) => iter.size_hint(),
10✔
279
            Self::DateTime(iter) => iter.size_hint(),
10✔
280
        }
281
    }
82✔
282
}
283

284
impl ExactSizeIterator for FloatOptionsIter<'_> {}
285

286
impl DoubleEndedIterator for FloatOptionsIter<'_> {
287
    fn next_back(&mut self) -> Option<Self::Item> {
24✔
288
        match self {
24✔
289
            Self::Category(iter) => iter.next_back(),
4✔
290
            Self::Int(iter) => iter.next_back(),
4✔
291
            Self::Float(iter) => iter.next_back(),
4✔
292
            Self::Text(iter) => iter.next_back(),
4✔
293
            Self::Bool(iter) => iter.next_back(),
4✔
294
            Self::DateTime(iter) => iter.next_back(),
4✔
295
        }
296
    }
24✔
297
}
298

299
impl ParallelIterator for FloatOptionsParIter<'_> {
300
    type Item = Option<f64>;
301

302
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
12✔
303
    where
12✔
304
        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
12✔
305
    {
12✔
306
        rayon::iter::plumbing::bridge(self, consumer)
12✔
307
    }
12✔
308
}
309

310
impl<'f> Producer for FloatOptionsParIter<'f> {
311
    type Item = Option<f64>;
312

313
    type IntoIter = FloatOptionsIter<'f>;
314

315
    fn into_iter(self) -> Self::IntoIter {
55✔
316
        self.0
55✔
317
    }
55✔
318

319
    fn split_at(self, index: usize) -> (Self, Self) {
38✔
320
        let (left, right) = match self.0 {
38✔
321
            FloatOptionsIter::Category(iter) => {
5✔
322
                let (left, right) = iter.split_at(index);
5✔
323
                (
5✔
324
                    FloatOptionsIter::Category(left),
5✔
325
                    FloatOptionsIter::Category(right),
5✔
326
                )
5✔
327
            }
328
            FloatOptionsIter::Int(iter) => {
5✔
329
                let (left, right) = iter.split_at(index);
5✔
330
                (FloatOptionsIter::Int(left), FloatOptionsIter::Int(right))
5✔
331
            }
332
            FloatOptionsIter::Float(iter) => {
13✔
333
                let (left, right) = iter.split_at(index);
13✔
334
                (
13✔
335
                    FloatOptionsIter::Float(left),
13✔
336
                    FloatOptionsIter::Float(right),
13✔
337
                )
13✔
338
            }
339
            FloatOptionsIter::Text(iter) => {
5✔
340
                let (left, right) = iter.split_at(index);
5✔
341
                (FloatOptionsIter::Text(left), FloatOptionsIter::Text(right))
5✔
342
            }
343
            FloatOptionsIter::Bool(iter) => {
5✔
344
                let (left, right) = iter.split_at(index);
5✔
345
                (FloatOptionsIter::Bool(left), FloatOptionsIter::Bool(right))
5✔
346
            }
347
            FloatOptionsIter::DateTime(iter) => {
5✔
348
                let (left, right) = iter.split_at(index);
5✔
349
                (
5✔
350
                    FloatOptionsIter::DateTime(left),
5✔
351
                    FloatOptionsIter::DateTime(right),
5✔
352
                )
5✔
353
            }
354
        };
355

356
        (left.into(), right.into())
38✔
357
    }
38✔
358
}
359

360
impl IndexedParallelIterator for FloatOptionsParIter<'_> {
361
    fn len(&self) -> usize {
52✔
362
        self.0.len()
52✔
363
    }
52✔
364

365
    fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
×
366
        rayon::iter::plumbing::bridge(self, consumer)
×
367
    }
×
368

369
    fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
23✔
370
        self,
23✔
371
        callback: CB,
23✔
372
    ) -> CB::Output {
23✔
373
        callback.callback(self)
23✔
374
    }
23✔
375
}
376

377
#[derive(Clone, Debug, PartialEq)]
378
pub struct FloatDataRef<'f> {
379
    buffer: &'f [f64],
380
    valid_bitmap: Option<&'f NullBuffer>,
381
}
382

383
impl<'f> DataRef<'f, f64> for FloatDataRef<'f> {
384
    fn json_value(value: &f64) -> serde_json::Value {
3✔
385
        (*value).into()
3✔
386
    }
3✔
387

388
    fn nulls(&self) -> Vec<bool> {
5✔
389
        null_bitmap_to_bools(self.valid_bitmap, self.as_ref().len())
5✔
390
    }
5✔
391

392
    fn is_valid(&self, i: usize) -> bool {
918✔
393
        self.valid_bitmap
918✔
394
            .as_ref()
918✔
395
            .map_or(true, |bitmap| bitmap.is_valid(i))
918✔
396
    }
918✔
397

398
    fn has_nulls(&self) -> bool {
16✔
399
        self.valid_bitmap.is_some()
16✔
400
    }
16✔
401

402
    fn get_unchecked(&self, i: usize) -> FeatureDataValue {
10✔
403
        if self.has_nulls() {
10✔
404
            FeatureDataValue::NullableFloat(if self.is_null(i) {
×
405
                None
×
406
            } else {
407
                Some(self.as_ref()[i])
×
408
            })
409
        } else {
410
            FeatureDataValue::Float(self.as_ref()[i])
10✔
411
        }
412
    }
10✔
413

414
    type StringsIter = NumberDataRefStringIter<'f, Self, f64>;
415

416
    fn strings_iter(&'f self) -> Self::StringsIter {
2✔
417
        NumberDataRefStringIter::new(self)
2✔
418
    }
2✔
419

420
    fn len(&self) -> usize {
43✔
421
        self.buffer.len()
43✔
422
    }
43✔
423

424
    type FloatOptionsIter = NumberDataRefFloatOptionIter<'f, Self, f64>;
425

426
    fn float_options_iter(&'f self) -> Self::FloatOptionsIter {
32✔
427
        NumberDataRefFloatOptionIter::new(self)
32✔
428
    }
32✔
429
}
430

431
pub struct NumberDataRefStringIter<'r, D, T>
432
where
433
    D: DataRef<'r, T>,
434
    T: 'static,
435
{
436
    data_ref: &'r D,
437
    index: usize,
438
    t: PhantomData<T>,
439
}
440

441
impl<'r, D, T> NumberDataRefStringIter<'r, D, T>
442
where
443
    D: DataRef<'r, T>,
444
    T: 'static,
445
{
446
    pub fn new(data_ref: &'r D) -> Self {
5✔
447
        Self {
5✔
448
            data_ref,
5✔
449
            index: 0,
5✔
450
            t: PhantomData,
5✔
451
        }
5✔
452
    }
5✔
453
}
454

455
impl<'f, D, T> Iterator for NumberDataRefStringIter<'f, D, T>
456
where
457
    D: DataRef<'f, T>,
458
    T: 'static + ToString,
459
{
460
    type Item = String;
461

462
    fn next(&mut self) -> Option<Self::Item> {
23✔
463
        if self.index >= self.data_ref.len() {
23✔
464
            return None;
5✔
465
        }
18✔
466

18✔
467
        let i = self.index;
18✔
468
        self.index += 1;
18✔
469

18✔
470
        if self.data_ref.is_null(i) {
18✔
471
            return Some(String::default());
5✔
472
        }
13✔
473

13✔
474
        Some(self.data_ref.as_ref()[i].to_string())
13✔
475
    }
23✔
476
}
477

478
#[derive(Debug, Clone)]
479
pub struct NumberDataRefFloatOptionIter<'r, D, T>
480
where
481
    D: DataRef<'r, T>,
482
    T: 'static,
483
{
484
    data_ref: &'r D,
485
    index: usize,
486
    length: usize,
487
    t: PhantomData<T>,
488
}
489

490
impl<'r, D, T> NumberDataRefFloatOptionIter<'r, D, T>
491
where
492
    D: DataRef<'r, T>,
493
    T: 'static,
494
{
495
    pub fn new(data_ref: &'r D) -> Self {
66✔
496
        Self {
66✔
497
            data_ref,
66✔
498
            index: 0,
66✔
499
            length: data_ref.len(),
66✔
500
            t: PhantomData,
66✔
501
        }
66✔
502
    }
66✔
503
}
504

505
impl<'f, D, T> Iterator for NumberDataRefFloatOptionIter<'f, D, T>
506
where
507
    D: DataRef<'f, T>,
508
    T: 'static + AsPrimitive<f64>,
509
{
510
    type Item = Option<f64>;
511

512
    fn next(&mut self) -> Option<Self::Item> {
58,438✔
513
        if self.index >= self.length {
58,438✔
514
            return None;
52✔
515
        }
58,386✔
516

58,386✔
517
        let i = self.index;
58,386✔
518
        self.index += 1;
58,386✔
519

58,386✔
520
        Some(if self.data_ref.is_null(i) {
58,386✔
521
            None
34✔
522
        } else {
523
            Some(self.data_ref.as_ref()[i].as_())
58,352✔
524
        })
525
    }
58,438✔
526

527
    fn size_hint(&self) -> (usize, Option<usize>) {
52✔
528
        let remaining = self.length - self.index;
52✔
529
        (remaining, Some(remaining))
52✔
530
    }
52✔
531
}
532

533
impl<'f, D, T> ExactSizeIterator for NumberDataRefFloatOptionIter<'f, D, T>
534
where
535
    D: DataRef<'f, T>,
536
    T: 'static + AsPrimitive<f64>,
537
{
538
}
539

540
impl<'f, D, T> DoubleEndedIterator for NumberDataRefFloatOptionIter<'f, D, T>
541
where
542
    D: DataRef<'f, T> + Send + Sync,
543
    T: 'static + AsPrimitive<f64> + Send,
544
{
545
    fn next_back(&mut self) -> Option<Self::Item> {
12✔
546
        if self.index >= self.length {
12✔
547
            return None;
3✔
548
        }
9✔
549

9✔
550
        let i = self.length - 1;
9✔
551
        self.length -= 1; // decrement!
9✔
552

9✔
553
        Some(if self.data_ref.is_null(i) {
9✔
554
            None
2✔
555
        } else {
556
            Some(self.data_ref.as_ref()[i].as_())
7✔
557
        })
558
    }
12✔
559
}
560

561
impl<'f, D, T> ParallelIterator for NumberDataRefFloatOptionIter<'f, D, T>
562
where
563
    D: DataRef<'f, T> + Send + Sync,
564
    T: 'static + AsPrimitive<f64> + Send,
565
{
566
    type Item = Option<f64>;
567

568
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
×
569
    where
×
570
        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
×
571
    {
×
572
        rayon::iter::plumbing::bridge(self, consumer)
×
573
    }
×
574
}
575

576
impl<'f, D, T> Producer for NumberDataRefFloatOptionIter<'f, D, T>
577
where
578
    D: DataRef<'f, T> + Send + Sync,
579
    T: 'static + AsPrimitive<f64> + Send,
580
{
581
    type Item = Option<f64>;
582

583
    type IntoIter = Self;
584

585
    fn into_iter(self) -> Self::IntoIter {
×
586
        self
×
587
    }
×
588

589
    fn split_at(self, index: usize) -> (Self, Self) {
23✔
590
        let (left_index, left_length_right_index, right_length) =
23✔
591
            indices_for_split_at(self.index, self.length, index);
23✔
592

23✔
593
        let left = Self::IntoIter {
23✔
594
            data_ref: self.data_ref,
23✔
595
            index: left_index,
23✔
596
            length: left_length_right_index,
23✔
597
            t: PhantomData,
23✔
598
        };
23✔
599

23✔
600
        let right = Self::IntoIter {
23✔
601
            data_ref: self.data_ref,
23✔
602
            index: left_length_right_index,
23✔
603
            length: right_length,
23✔
604
            t: PhantomData,
23✔
605
        };
23✔
606

23✔
607
        (left, right)
23✔
608
    }
23✔
609
}
610

611
impl<'f, D, T> IndexedParallelIterator for NumberDataRefFloatOptionIter<'f, D, T>
612
where
613
    D: DataRef<'f, T> + Send + Sync,
614
    T: 'static + AsPrimitive<f64> + Send,
615
{
616
    fn len(&self) -> usize {
×
617
        ExactSizeIterator::len(self)
×
618
    }
×
619

620
    fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
×
621
        rayon::iter::plumbing::bridge(self, consumer)
×
622
    }
×
623

624
    fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
×
625
        self,
×
626
        callback: CB,
×
627
    ) -> CB::Output {
×
628
        callback.callback(self)
×
629
    }
×
630
}
631

632
impl AsRef<[f64]> for FloatDataRef<'_> {
633
    fn as_ref(&self) -> &[f64] {
919✔
634
        self.buffer
919✔
635
    }
919✔
636
}
637

638
impl<'f> From<FloatDataRef<'f>> for FeatureDataRef<'f> {
639
    fn from(data_ref: FloatDataRef<'f>) -> FeatureDataRef<'f> {
49✔
640
        FeatureDataRef::Float(data_ref)
49✔
641
    }
49✔
642
}
643

644
impl<'f> FloatDataRef<'f> {
645
    pub fn new(buffer: &'f [f64], null_bitmap: Option<&'f NullBuffer>) -> Self {
52✔
646
        Self {
52✔
647
            buffer,
52✔
648
            valid_bitmap: null_bitmap,
52✔
649
        }
52✔
650
    }
52✔
651
}
652

653
#[derive(Clone, Debug, PartialEq)]
654
pub struct IntDataRef<'f> {
655
    buffer: &'f [i64],
656
    valid_bitmap: Option<&'f NullBuffer>,
657
}
658

659
impl<'f> IntDataRef<'f> {
660
    pub fn new(buffer: &'f [i64], null_bitmap: Option<&'f NullBuffer>) -> Self {
72✔
661
        Self {
72✔
662
            buffer,
72✔
663
            valid_bitmap: null_bitmap,
72✔
664
        }
72✔
665
    }
72✔
666
}
667

668
impl<'f> DataRef<'f, i64> for IntDataRef<'f> {
669
    fn json_value(value: &i64) -> serde_json::Value {
5✔
670
        (*value).into()
5✔
671
    }
5✔
672

673
    fn nulls(&self) -> Vec<bool> {
2✔
674
        null_bitmap_to_bools(self.valid_bitmap, self.as_ref().len())
2✔
675
    }
2✔
676

677
    fn is_valid(&self, i: usize) -> bool {
57,489✔
678
        self.valid_bitmap
57,489✔
679
            .as_ref()
57,489✔
680
            .map_or(true, |bitmap| bitmap.is_valid(i))
57,489✔
681
    }
57,489✔
682

683
    fn has_nulls(&self) -> bool {
38✔
684
        self.valid_bitmap.is_some()
38✔
685
    }
38✔
686

687
    fn get_unchecked(&self, i: usize) -> FeatureDataValue {
30✔
688
        if self.has_nulls() {
30✔
689
            FeatureDataValue::NullableInt(if self.is_null(i) {
7✔
690
                None
4✔
691
            } else {
692
                Some(self.as_ref()[i])
3✔
693
            })
694
        } else {
695
            FeatureDataValue::Int(self.as_ref()[i])
23✔
696
        }
697
    }
30✔
698

699
    type StringsIter = NumberDataRefStringIter<'f, Self, i64>;
700

701
    fn strings_iter(&'f self) -> Self::StringsIter {
1✔
702
        NumberDataRefStringIter::new(self)
1✔
703
    }
1✔
704

705
    fn len(&self) -> usize {
34✔
706
        self.buffer.len()
34✔
707
    }
34✔
708

709
    type FloatOptionsIter = NumberDataRefFloatOptionIter<'f, Self, i64>;
710

711
    fn float_options_iter(&'f self) -> Self::FloatOptionsIter {
30✔
712
        NumberDataRefFloatOptionIter::new(self)
30✔
713
    }
30✔
714
}
715

716
impl AsRef<[i64]> for IntDataRef<'_> {
717
    fn as_ref(&self) -> &[i64] {
57,540✔
718
        self.buffer
57,540✔
719
    }
57,540✔
720
}
721

722
impl<'f> From<IntDataRef<'f>> for FeatureDataRef<'f> {
723
    fn from(data_ref: IntDataRef<'f>) -> FeatureDataRef<'f> {
70✔
724
        FeatureDataRef::Int(data_ref)
70✔
725
    }
70✔
726
}
727

728
fn null_bitmap_to_bools(null_bitmap: Option<&NullBuffer>, len: usize) -> Vec<bool> {
8✔
729
    if let Some(nulls) = null_bitmap {
8✔
730
        (0..len).map(|i| !nulls.is_valid(i)).collect()
28✔
731
    } else {
732
        vec![false; len]
×
733
    }
734
}
8✔
735

736
#[derive(Clone, Debug, PartialEq)]
737
pub struct BoolDataRef<'f> {
738
    buffer: Vec<bool>,
739
    valid_bitmap: Option<&'f NullBuffer>,
740
}
741

742
impl<'f> BoolDataRef<'f> {
743
    pub fn new(buffer: Vec<bool>, null_bitmap: Option<&'f NullBuffer>) -> Self {
3✔
744
        Self {
3✔
745
            buffer,
3✔
746
            valid_bitmap: null_bitmap,
3✔
747
        }
3✔
748
    }
3✔
749
}
750

751
impl<'f> DataRef<'f, bool> for BoolDataRef<'f> {
752
    fn json_value(value: &bool) -> serde_json::Value {
×
753
        (*value).into()
×
754
    }
×
755

756
    fn nulls(&self) -> Vec<bool> {
×
757
        null_bitmap_to_bools(self.valid_bitmap, self.as_ref().len())
×
758
    }
×
759

760
    fn is_valid(&self, i: usize) -> bool {
15✔
761
        self.valid_bitmap
15✔
762
            .as_ref()
15✔
763
            .map_or(true, |bitmap| bitmap.is_valid(i))
15✔
764
    }
15✔
765

766
    fn has_nulls(&self) -> bool {
×
767
        self.valid_bitmap.is_some()
×
768
    }
×
769

770
    fn get_unchecked(&self, i: usize) -> FeatureDataValue {
×
771
        if self.has_nulls() {
×
772
            FeatureDataValue::NullableBool(if self.is_null(i) {
×
773
                None
×
774
            } else {
775
                Some(self.as_ref()[i])
×
776
            })
777
        } else {
778
            FeatureDataValue::Bool(self.as_ref()[i])
×
779
        }
780
    }
×
781

782
    type StringsIter = NumberDataRefStringIter<'f, Self, bool>;
783

784
    fn strings_iter(&'f self) -> Self::StringsIter {
1✔
785
        NumberDataRefStringIter::new(self)
1✔
786
    }
1✔
787

788
    fn len(&self) -> usize {
8✔
789
        self.buffer.len()
8✔
790
    }
8✔
791

792
    type FloatOptionsIter = BoolDataRefFloatOptionIter<'f>;
793

794
    fn float_options_iter(&'f self) -> Self::FloatOptionsIter {
4✔
795
        BoolDataRefFloatOptionIter::new(self)
4✔
796
    }
4✔
797
}
798

799
impl AsRef<[bool]> for BoolDataRef<'_> {
800
    fn as_ref(&self) -> &[bool] {
10✔
801
        &self.buffer
10✔
802
    }
10✔
803
}
804

805
impl<'f> From<BoolDataRef<'f>> for FeatureDataRef<'f> {
806
    fn from(data_ref: BoolDataRef<'f>) -> Self {
3✔
807
        FeatureDataRef::Bool(data_ref)
3✔
808
    }
3✔
809
}
810

811
#[derive(Debug, Clone)]
812
pub struct BoolDataRefFloatOptionIter<'f> {
813
    data_ref: &'f BoolDataRef<'f>,
814
    index: usize,
815
    length: usize,
816
}
817

818
impl<'f> BoolDataRefFloatOptionIter<'f> {
819
    pub fn new(data_ref: &'f BoolDataRef<'f>) -> Self {
4✔
820
        Self {
4✔
821
            data_ref,
4✔
822
            index: 0,
4✔
823
            length: data_ref.len(),
4✔
824
        }
4✔
825
    }
4✔
826
}
827

828
impl Iterator for BoolDataRefFloatOptionIter<'_> {
829
    type Item = Option<f64>;
830

831
    fn next(&mut self) -> Option<Self::Item> {
16✔
832
        if self.index >= self.length {
16✔
833
            return None;
7✔
834
        }
9✔
835

9✔
836
        let i = self.index;
9✔
837
        self.index += 1;
9✔
838

9✔
839
        Some(if self.data_ref.is_null(i) {
9✔
840
            None
3✔
841
        } else {
842
            Some(f64::from(u8::from(self.data_ref.as_ref()[i])))
6✔
843
        })
844
    }
16✔
845

846
    fn size_hint(&self) -> (usize, Option<usize>) {
10✔
847
        let remaining = self.length - self.index;
10✔
848
        (remaining, Some(remaining))
10✔
849
    }
10✔
850
}
851

852
impl ExactSizeIterator for BoolDataRefFloatOptionIter<'_> {}
853

854
impl DoubleEndedIterator for BoolDataRefFloatOptionIter<'_> {
855
    fn next_back(&mut self) -> Option<Self::Item> {
4✔
856
        if self.index >= self.length {
4✔
857
            return None;
1✔
858
        }
3✔
859

3✔
860
        let i = self.length - 1;
3✔
861
        self.length -= 1; // decrement!
3✔
862

3✔
863
        Some(if self.data_ref.is_null(i) {
3✔
864
            None
1✔
865
        } else {
866
            Some(f64::from(u8::from(self.data_ref.as_ref()[i])))
2✔
867
        })
868
    }
4✔
869
}
870

871
impl ParallelIterator for BoolDataRefFloatOptionIter<'_> {
872
    type Item = Option<f64>;
873

874
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
×
875
    where
×
876
        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
×
877
    {
×
878
        rayon::iter::plumbing::bridge(self, consumer)
×
879
    }
×
880
}
881

882
impl Producer for BoolDataRefFloatOptionIter<'_> {
883
    type Item = Option<f64>;
884

885
    type IntoIter = Self;
886

887
    fn into_iter(self) -> Self::IntoIter {
×
888
        self
×
889
    }
×
890

891
    fn split_at(self, index: usize) -> (Self, Self) {
5✔
892
        let (left_index, left_length_right_index, right_length) =
5✔
893
            indices_for_split_at(self.index, self.length, index);
5✔
894

5✔
895
        let left = Self::IntoIter {
5✔
896
            data_ref: self.data_ref,
5✔
897
            index: left_index,
5✔
898
            length: left_length_right_index,
5✔
899
        };
5✔
900

5✔
901
        let right = Self::IntoIter {
5✔
902
            data_ref: self.data_ref,
5✔
903
            index: left_length_right_index,
5✔
904
            length: right_length,
5✔
905
        };
5✔
906

5✔
907
        (left, right)
5✔
908
    }
5✔
909
}
910

911
impl IndexedParallelIterator for BoolDataRefFloatOptionIter<'_> {
912
    fn len(&self) -> usize {
×
913
        ExactSizeIterator::len(self)
×
914
    }
×
915

916
    fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
×
917
        rayon::iter::plumbing::bridge(self, consumer)
×
918
    }
×
919

920
    fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
×
921
        self,
×
922
        callback: CB,
×
923
    ) -> CB::Output {
×
924
        callback.callback(self)
×
925
    }
×
926
}
927

928
#[derive(Clone, Debug, PartialEq)]
929
pub struct DateTimeDataRef<'f> {
930
    buffer: &'f [TimeInstance],
931
    valid_bitmap: Option<&'f NullBuffer>,
932
}
933

934
impl<'f> DateTimeDataRef<'f> {
935
    pub fn new(buffer: &'f [TimeInstance], null_bitmap: Option<&'f NullBuffer>) -> Self {
3✔
936
        Self {
3✔
937
            buffer,
3✔
938
            valid_bitmap: null_bitmap,
3✔
939
        }
3✔
940
    }
3✔
941
}
942

943
impl<'f> DataRef<'f, TimeInstance> for DateTimeDataRef<'f> {
944
    fn json_value(value: &TimeInstance) -> serde_json::Value {
×
945
        serde_json::to_value(value).expect("TimeInstance can be serialized")
×
946
    }
×
947

948
    fn nulls(&self) -> Vec<bool> {
×
949
        null_bitmap_to_bools(self.valid_bitmap, self.as_ref().len())
×
950
    }
×
951

952
    fn is_valid(&self, i: usize) -> bool {
15✔
953
        self.valid_bitmap
15✔
954
            .as_ref()
15✔
955
            .map_or(true, |bitmap| bitmap.is_valid(i))
15✔
956
    }
15✔
957

958
    fn has_nulls(&self) -> bool {
×
959
        self.valid_bitmap.is_some()
×
960
    }
×
961

962
    fn get_unchecked(&self, i: usize) -> FeatureDataValue {
×
963
        if self.has_nulls() {
×
964
            FeatureDataValue::NullableDateTime(if self.is_null(i) {
×
965
                None
×
966
            } else {
967
                Some(self.as_ref()[i])
×
968
            })
969
        } else {
970
            FeatureDataValue::DateTime(self.as_ref()[i])
×
971
        }
972
    }
×
973

974
    type StringsIter = NumberDataRefStringIter<'f, Self, TimeInstance>;
975

976
    fn strings_iter(&'f self) -> Self::StringsIter {
1✔
977
        NumberDataRefStringIter::new(self)
1✔
978
    }
1✔
979

980
    fn len(&self) -> usize {
8✔
981
        self.buffer.len()
8✔
982
    }
8✔
983

984
    type FloatOptionsIter = DateTimeDataRefFloatOptionIter<'f>;
985

986
    fn float_options_iter(&'f self) -> Self::FloatOptionsIter {
4✔
987
        Self::FloatOptionsIter::new(self)
4✔
988
    }
4✔
989
}
990

991
impl AsRef<[TimeInstance]> for DateTimeDataRef<'_> {
992
    fn as_ref(&self) -> &[TimeInstance] {
10✔
993
        self.buffer
10✔
994
    }
10✔
995
}
996

997
impl<'f> From<DateTimeDataRef<'f>> for FeatureDataRef<'f> {
998
    fn from(data_ref: DateTimeDataRef<'f>) -> Self {
3✔
999
        FeatureDataRef::DateTime(data_ref)
3✔
1000
    }
3✔
1001
}
1002

1003
#[derive(Debug, Clone)]
1004
pub struct DateTimeDataRefFloatOptionIter<'f> {
1005
    data_ref: &'f DateTimeDataRef<'f>,
1006
    index: usize,
1007
    length: usize,
1008
}
1009

1010
impl<'f> DateTimeDataRefFloatOptionIter<'f> {
1011
    pub fn new(data_ref: &'f DateTimeDataRef<'f>) -> Self {
4✔
1012
        Self {
4✔
1013
            data_ref,
4✔
1014
            index: 0,
4✔
1015
            length: data_ref.len(),
4✔
1016
        }
4✔
1017
    }
4✔
1018
}
1019

1020
impl Iterator for DateTimeDataRefFloatOptionIter<'_> {
1021
    type Item = Option<f64>;
1022

1023
    fn next(&mut self) -> Option<Self::Item> {
16✔
1024
        if self.index >= self.length {
16✔
1025
            return None;
7✔
1026
        }
9✔
1027

9✔
1028
        let i = self.index;
9✔
1029
        self.index += 1;
9✔
1030

9✔
1031
        Some(if self.data_ref.is_null(i) {
9✔
1032
            None
3✔
1033
        } else {
1034
            Some(self.data_ref.as_ref()[i].inner() as f64)
6✔
1035
        })
1036
    }
16✔
1037

1038
    fn size_hint(&self) -> (usize, Option<usize>) {
10✔
1039
        let remaining = self.length - self.index;
10✔
1040
        (remaining, Some(remaining))
10✔
1041
    }
10✔
1042
}
1043

1044
impl ExactSizeIterator for DateTimeDataRefFloatOptionIter<'_> {}
1045

1046
impl DoubleEndedIterator for DateTimeDataRefFloatOptionIter<'_> {
1047
    fn next_back(&mut self) -> Option<Self::Item> {
4✔
1048
        if self.index >= self.length {
4✔
1049
            return None;
1✔
1050
        }
3✔
1051

3✔
1052
        let i = self.length - 1;
3✔
1053
        self.length -= 1; // decrement!
3✔
1054

3✔
1055
        Some(if self.data_ref.is_null(i) {
3✔
1056
            None
1✔
1057
        } else {
1058
            Some(self.data_ref.as_ref()[i].inner() as f64)
2✔
1059
        })
1060
    }
4✔
1061
}
1062

1063
impl ParallelIterator for DateTimeDataRefFloatOptionIter<'_> {
1064
    type Item = Option<f64>;
1065

1066
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
×
1067
    where
×
1068
        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
×
1069
    {
×
1070
        rayon::iter::plumbing::bridge(self, consumer)
×
1071
    }
×
1072
}
1073

1074
impl Producer for DateTimeDataRefFloatOptionIter<'_> {
1075
    type Item = Option<f64>;
1076

1077
    type IntoIter = Self;
1078

1079
    fn into_iter(self) -> Self::IntoIter {
×
1080
        self
×
1081
    }
×
1082

1083
    fn split_at(self, index: usize) -> (Self, Self) {
5✔
1084
        let (left_index, left_length_right_index, right_length) =
5✔
1085
            indices_for_split_at(self.index, self.length, index);
5✔
1086

5✔
1087
        let left = Self::IntoIter {
5✔
1088
            data_ref: self.data_ref,
5✔
1089
            index: left_index,
5✔
1090
            length: left_length_right_index,
5✔
1091
        };
5✔
1092

5✔
1093
        let right = Self::IntoIter {
5✔
1094
            data_ref: self.data_ref,
5✔
1095
            index: left_length_right_index,
5✔
1096
            length: right_length,
5✔
1097
        };
5✔
1098

5✔
1099
        (left, right)
5✔
1100
    }
5✔
1101
}
1102

1103
impl IndexedParallelIterator for DateTimeDataRefFloatOptionIter<'_> {
1104
    fn len(&self) -> usize {
×
1105
        ExactSizeIterator::len(self)
×
1106
    }
×
1107

1108
    fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
×
1109
        rayon::iter::plumbing::bridge(self, consumer)
×
1110
    }
×
1111

1112
    fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
×
1113
        self,
×
1114
        callback: CB,
×
1115
    ) -> CB::Output {
×
1116
        callback.callback(self)
×
1117
    }
×
1118
}
1119

1120
#[derive(Clone, Debug, PartialEq)]
1121
pub struct CategoryDataRef<'f> {
1122
    buffer: &'f [u8],
1123
    valid_bitmap: Option<&'f NullBuffer>,
1124
}
1125

1126
impl<'f> DataRef<'f, u8> for CategoryDataRef<'f> {
1127
    fn json_value(value: &u8) -> serde_json::Value {
×
1128
        (*value).into()
×
1129
    }
×
1130

1131
    fn nulls(&self) -> Vec<bool> {
×
1132
        null_bitmap_to_bools(self.valid_bitmap, self.as_ref().len())
×
1133
    }
×
1134

1135
    fn is_valid(&self, i: usize) -> bool {
12✔
1136
        self.valid_bitmap
12✔
1137
            .as_ref()
12✔
1138
            .map_or(true, |bitmap| bitmap.is_valid(i))
12✔
1139
    }
12✔
1140

1141
    fn has_nulls(&self) -> bool {
1✔
1142
        self.valid_bitmap.is_some()
1✔
1143
    }
1✔
1144

1145
    fn get_unchecked(&self, i: usize) -> FeatureDataValue {
×
1146
        if self.has_nulls() {
×
1147
            FeatureDataValue::NullableCategory(if self.is_null(i) {
×
1148
                None
×
1149
            } else {
1150
                Some(self.as_ref()[i])
×
1151
            })
1152
        } else {
1153
            FeatureDataValue::Category(self.as_ref()[i])
×
1154
        }
1155
    }
×
1156

1157
    type StringsIter = NumberDataRefStringIter<'f, Self, u8>;
1158

1159
    fn strings_iter(&'f self) -> Self::StringsIter {
×
1160
        NumberDataRefStringIter::new(self)
×
1161
    }
×
1162

1163
    fn len(&self) -> usize {
4✔
1164
        self.buffer.len()
4✔
1165
    }
4✔
1166

1167
    type FloatOptionsIter = NumberDataRefFloatOptionIter<'f, Self, u8>;
1168

1169
    fn float_options_iter(&'f self) -> Self::FloatOptionsIter {
4✔
1170
        NumberDataRefFloatOptionIter::new(self)
4✔
1171
    }
4✔
1172
}
1173

1174
impl AsRef<[u8]> for CategoryDataRef<'_> {
1175
    fn as_ref(&self) -> &[u8] {
9✔
1176
        self.buffer
9✔
1177
    }
9✔
1178
}
1179

1180
impl<'f> From<CategoryDataRef<'f>> for FeatureDataRef<'f> {
1181
    fn from(data_ref: CategoryDataRef<'f>) -> FeatureDataRef<'f> {
2✔
1182
        FeatureDataRef::Category(data_ref)
2✔
1183
    }
2✔
1184
}
1185

1186
impl<'f> CategoryDataRef<'f> {
1187
    pub fn new(buffer: &'f [u8], null_bitmap: Option<&'f NullBuffer>) -> Self {
3✔
1188
        Self {
3✔
1189
            buffer,
3✔
1190
            valid_bitmap: null_bitmap,
3✔
1191
        }
3✔
1192
    }
3✔
1193
}
1194

1195
unsafe fn byte_ptr_to_str<'d>(bytes: *const u8, length: usize) -> &'d str {
95✔
1196
    let text_ref = slice::from_raw_parts(bytes, length);
95✔
1197
    str::from_utf8_unchecked(text_ref)
95✔
1198
}
95✔
1199

1200
/// A reference to nullable text data
1201
///
1202
/// # Examples
1203
///
1204
/// ```rust
1205
/// use geoengine_datatypes::primitives::TextDataRef;
1206
/// use arrow::array::{StringBuilder, Array};
1207
///
1208
/// let string_array = {
1209
///     let mut builder = StringBuilder::with_capacity(3, 6+3);
1210
///     builder.append_value("foobar");
1211
///     builder.append_null();
1212
///     builder.append_value("bar");
1213
///     builder.finish()
1214
/// };
1215
///
1216
/// assert_eq!(string_array.len(), 3);
1217
///
1218
/// let text_data_ref = TextDataRef::new(string_array.value_data(), string_array.value_offsets(), string_array.nulls());
1219
///
1220
/// assert_eq!(text_data_ref.as_ref().len(), 9);
1221
/// assert_eq!(text_data_ref.offsets().len(), 4);
1222
///
1223
/// assert_eq!(text_data_ref.text_at(0).unwrap(), Some("foobar"));
1224
/// assert_eq!(text_data_ref.text_at(1).unwrap(), None);
1225
/// assert_eq!(text_data_ref.text_at(2).unwrap(), Some("bar"));
1226
/// assert!(text_data_ref.text_at(3).is_err());
1227
/// ```
1228
///
1229
#[derive(Clone, Debug, PartialEq)]
1230
pub struct TextDataRef<'f> {
1231
    data_buffer: &'f [u8],
1232
    offsets: &'f [i32],
1233
    valid_bitmap: Option<&'f NullBuffer>,
1234
}
1235

1236
impl AsRef<[u8]> for TextDataRef<'_> {
1237
    fn as_ref(&self) -> &[u8] {
×
1238
        self.data_buffer
×
1239
    }
×
1240
}
1241

1242
impl<'r> DataRef<'r, u8> for TextDataRef<'r> {
1243
    fn json_values(&'r self) -> Box<dyn Iterator<Item = serde_json::Value> + 'r> {
1✔
1244
        let offsets = self.offsets;
1✔
1245
        let number_of_values = offsets.len() - 1;
1✔
1246

1✔
1247
        Box::new((0..number_of_values).map(move |pos| {
3✔
1248
            let start = offsets[pos];
3✔
1249
            let end = offsets[pos + 1];
3✔
1250

3✔
1251
            if start == end {
3✔
1252
                return if self.is_valid(pos) {
1✔
1253
                    serde_json::Value::String(String::default())
×
1254
                } else {
1255
                    serde_json::Value::Null
1✔
1256
                };
1257
            }
2✔
1258

2✔
1259
            let text = unsafe {
2✔
1260
                byte_ptr_to_str(
2✔
1261
                    self.data_buffer[start as usize..].as_ptr(),
2✔
1262
                    (end - start) as usize,
2✔
1263
                )
2✔
1264
            };
2✔
1265

2✔
1266
            text.into()
2✔
1267
        }))
3✔
1268
    }
1✔
1269

1270
    fn json_value(value: &u8) -> Value {
×
1271
        (*value).into()
×
1272
    }
×
1273

1274
    /// A null vector for text data
1275
    ///
1276
    /// # Examples
1277
    ///
1278
    /// ```rust
1279
    /// use geoengine_datatypes::primitives::{TextDataRef, DataRef};
1280
    /// use arrow::array::{StringBuilder, Array};
1281
    ///
1282
    /// let string_array = {
1283
    ///     let mut builder = StringBuilder::with_capacity(3, 6+3);
1284
    ///     builder.append_value("foobar");
1285
    ///     builder.append_null();
1286
    ///     builder.append_value("bar");
1287
    ///     builder.finish()
1288
    /// };
1289
    ///
1290
    /// assert_eq!(string_array.len(), 3);
1291
    ///
1292
    /// let text_data_ref = TextDataRef::new(string_array.value_data(), string_array.value_offsets(), string_array.nulls());
1293
    ///
1294
    /// assert_eq!(text_data_ref.nulls(), vec![false, true, false]);
1295
    /// ```
1296
    ///
1297
    fn nulls(&self) -> Vec<bool> {
1✔
1298
        null_bitmap_to_bools(self.valid_bitmap, self.offsets.len() - 1)
1✔
1299
    }
1✔
1300

1301
    fn is_valid(&self, i: usize) -> bool {
15✔
1302
        self.valid_bitmap
15✔
1303
            .as_ref()
15✔
1304
            .map_or(true, |bitmap| bitmap.is_valid(i))
15✔
1305
    }
15✔
1306

1307
    fn has_nulls(&self) -> bool {
27✔
1308
        self.valid_bitmap.is_some()
27✔
1309
    }
27✔
1310

1311
    fn get_unchecked(&self, i: usize) -> FeatureDataValue {
25✔
1312
        let text = self.text_at(i).expect("unchecked").map(ToString::to_string);
25✔
1313

25✔
1314
        if self.has_nulls() {
25✔
1315
            FeatureDataValue::NullableText(text)
14✔
1316
        } else {
1317
            FeatureDataValue::Text(text.expect("cannot be null"))
11✔
1318
        }
1319
    }
25✔
1320

1321
    type StringsIter = TextDataRefStringIter<'r>;
1322

1323
    fn strings_iter(&'r self) -> Self::StringsIter {
51✔
1324
        Self::StringsIter::new(self)
51✔
1325
    }
51✔
1326

1327
    fn len(&self) -> usize {
4✔
1328
        self.offsets.len() - 1
4✔
1329
    }
4✔
1330

1331
    type FloatOptionsIter = TextDataRefFloatOptionIter<'r>;
1332

1333
    fn float_options_iter(&'r self) -> Self::FloatOptionsIter {
4✔
1334
        Self::FloatOptionsIter::new(self)
4✔
1335
    }
4✔
1336
}
1337

1338
pub struct TextDataRefStringIter<'r> {
1339
    data_ref: &'r TextDataRef<'r>,
1340
    i: usize,
1341
}
1342

1343
impl<'r> TextDataRefStringIter<'r> {
1344
    pub fn new(data_ref: &'r TextDataRef<'r>) -> Self {
51✔
1345
        Self { data_ref, i: 0 }
51✔
1346
    }
51✔
1347
}
1348

1349
impl Iterator for TextDataRefStringIter<'_> {
1350
    type Item = String;
1351

1352
    fn next(&mut self) -> Option<Self::Item> {
113✔
1353
        let i = self.i;
113✔
1354
        self.i += 1;
113✔
1355

113✔
1356
        self.data_ref
113✔
1357
            .text_at(i)
113✔
1358
            .map(|text_option| match text_option {
113✔
1359
                Some(text) => text.to_owned(),
60✔
1360
                None => String::default(),
2✔
1361
            })
113✔
1362
            .ok()
113✔
1363
    }
113✔
1364
}
1365

1366
#[derive(Debug, Clone)]
1367
pub struct TextDataRefFloatOptionIter<'r> {
1368
    data_ref: &'r TextDataRef<'r>,
1369
    index: usize,
1370
    length: usize,
1371
}
1372

1373
impl<'r> TextDataRefFloatOptionIter<'r> {
1374
    pub fn new(data_ref: &'r TextDataRef<'r>) -> Self {
4✔
1375
        Self {
4✔
1376
            data_ref,
4✔
1377
            index: 0,
4✔
1378
            length: data_ref.len(),
4✔
1379
        }
4✔
1380
    }
4✔
1381
}
1382

1383
impl Iterator for TextDataRefFloatOptionIter<'_> {
1384
    type Item = Option<f64>;
1385

1386
    fn next(&mut self) -> Option<Self::Item> {
16✔
1387
        if self.index >= self.length {
16✔
1388
            return None;
7✔
1389
        }
9✔
1390

9✔
1391
        let i = self.index;
9✔
1392
        self.index += 1;
9✔
1393

9✔
1394
        self.data_ref
9✔
1395
            .text_at(i)
9✔
1396
            .map(|text_option| match text_option {
9✔
1397
                Some(text) => text.parse().ok(),
6✔
1398
                None => None,
3✔
1399
            })
9✔
1400
            .ok()
9✔
1401
    }
16✔
1402

1403
    fn size_hint(&self) -> (usize, Option<usize>) {
10✔
1404
        let remaining = self.length - self.index;
10✔
1405
        (remaining, Some(remaining))
10✔
1406
    }
10✔
1407
}
1408

1409
impl ExactSizeIterator for TextDataRefFloatOptionIter<'_> {}
1410

1411
impl DoubleEndedIterator for TextDataRefFloatOptionIter<'_> {
1412
    fn next_back(&mut self) -> Option<Self::Item> {
4✔
1413
        if self.index >= self.length {
4✔
1414
            return None;
1✔
1415
        }
3✔
1416

3✔
1417
        let i = self.length - 1;
3✔
1418
        self.length -= 1; // decrement!
3✔
1419

3✔
1420
        self.data_ref
3✔
1421
            .text_at(i)
3✔
1422
            .map(|text_option| match text_option {
3✔
1423
                Some(text) => text.parse().ok(),
2✔
1424
                None => None,
1✔
1425
            })
3✔
1426
            .ok()
3✔
1427
    }
4✔
1428
}
1429

1430
impl ParallelIterator for TextDataRefFloatOptionIter<'_> {
1431
    type Item = Option<f64>;
1432

1433
    fn drive_unindexed<C>(self, consumer: C) -> C::Result
×
1434
    where
×
1435
        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
×
1436
    {
×
1437
        rayon::iter::plumbing::bridge(self, consumer)
×
1438
    }
×
1439
}
1440

1441
impl Producer for TextDataRefFloatOptionIter<'_> {
1442
    type Item = Option<f64>;
1443

1444
    type IntoIter = Self;
1445

1446
    fn into_iter(self) -> Self::IntoIter {
×
1447
        self
×
1448
    }
×
1449

1450
    fn split_at(self, index: usize) -> (Self, Self) {
5✔
1451
        let (left_index, left_length_right_index, right_length) =
5✔
1452
            indices_for_split_at(self.index, self.length, index);
5✔
1453

5✔
1454
        let left = Self::IntoIter {
5✔
1455
            data_ref: self.data_ref,
5✔
1456
            index: left_index,
5✔
1457
            length: left_length_right_index,
5✔
1458
        };
5✔
1459

5✔
1460
        let right = Self::IntoIter {
5✔
1461
            data_ref: self.data_ref,
5✔
1462
            index: left_length_right_index,
5✔
1463
            length: right_length,
5✔
1464
        };
5✔
1465

5✔
1466
        (left, right)
5✔
1467
    }
5✔
1468
}
1469

1470
impl IndexedParallelIterator for TextDataRefFloatOptionIter<'_> {
1471
    fn len(&self) -> usize {
×
1472
        ExactSizeIterator::len(self)
×
1473
    }
×
1474

1475
    fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
×
1476
        rayon::iter::plumbing::bridge(self, consumer)
×
1477
    }
×
1478

1479
    fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
×
1480
        self,
×
1481
        callback: CB,
×
1482
    ) -> CB::Output {
×
1483
        callback.callback(self)
×
1484
    }
×
1485
}
1486

1487
impl<'r> From<TextDataRef<'r>> for FeatureDataRef<'r> {
1488
    fn from(data_ref: TextDataRef<'r>) -> Self {
66✔
1489
        Self::Text(data_ref)
66✔
1490
    }
66✔
1491
}
1492

1493
impl<'r> TextDataRef<'r> {
1494
    pub fn new(
66✔
1495
        data_buffer: &'r [u8],
66✔
1496
        offsets: &'r [i32],
66✔
1497
        valid_bitmap: Option<&'r NullBuffer>,
66✔
1498
    ) -> Self {
66✔
1499
        Self {
66✔
1500
            data_buffer,
66✔
1501
            offsets,
66✔
1502
            valid_bitmap,
66✔
1503
        }
66✔
1504
    }
66✔
1505

1506
    /// Returns the offsets of the individual strings
1507
    pub fn offsets(&self) -> &[i32] {
×
1508
        self.offsets
×
1509
    }
×
1510

1511
    /// Returns the text reference at a certain position in the feature collection
1512
    ///
1513
    /// # Errors
1514
    ///
1515
    /// This method fails if `pos` is out of bounds
1516
    ///
1517
    pub fn text_at(&self, pos: usize) -> Result<Option<&str>> {
158✔
1518
        ensure!(
158✔
1519
            pos < (self.offsets.len() - 1),
158✔
1520
            error::FeatureData {
51✔
1521
                details: "Position must be in data range"
51✔
1522
            }
51✔
1523
        );
1524

1525
        let start = self.offsets[pos];
107✔
1526
        let end = self.offsets[pos + 1];
107✔
1527

107✔
1528
        if start == end {
107✔
1529
            return Ok(if self.is_valid(pos) { Some("") } else { None });
14✔
1530
        }
93✔
1531

93✔
1532
        let text = unsafe {
93✔
1533
            byte_ptr_to_str(
93✔
1534
                self.data_buffer[start as usize..].as_ptr(),
93✔
1535
                (end - start) as usize,
93✔
1536
            )
93✔
1537
        };
93✔
1538

93✔
1539
        Ok(Some(text))
93✔
1540
    }
158✔
1541
}
1542

1543
impl FeatureDataType {
1544
    pub fn arrow_data_type(self) -> arrow::datatypes::DataType {
1,754✔
1545
        match self {
1,754✔
1546
            Self::Text => arrow::datatypes::DataType::Utf8,
674✔
1547
            Self::Float => arrow::datatypes::DataType::Float64,
789✔
1548
            Self::Int => arrow::datatypes::DataType::Int64,
269✔
1549
            Self::Category => arrow::datatypes::DataType::UInt8,
4✔
1550
            Self::Bool => arrow::datatypes::DataType::Boolean,
9✔
1551
            Self::DateTime => arrow::datatypes::DataType::Date64,
9✔
1552
        }
1553
    }
1,754✔
1554

1555
    #[allow(clippy::unused_self)]
1556
    pub fn nullable(self) -> bool {
1,754✔
1557
        true
1,754✔
1558
    }
1,754✔
1559

1560
    pub fn null_feature_data(self, len: usize) -> FeatureData {
×
1561
        match self {
×
1562
            Self::Text => FeatureData::NullableText(vec![None; len]),
×
1563
            Self::Float => FeatureData::NullableFloat(vec![None; len]),
×
1564
            Self::Int => FeatureData::NullableInt(vec![None; len]),
×
1565
            Self::Category => FeatureData::NullableCategory(vec![None; len]),
×
1566
            Self::Bool => FeatureData::NullableBool(vec![None; len]),
×
1567
            Self::DateTime => FeatureData::NullableDateTime(vec![None; len]),
×
1568
        }
1569
    }
×
1570

1571
    pub fn arrow_builder(self, len: usize) -> Box<dyn arrow::array::ArrayBuilder> {
899✔
1572
        match self {
899✔
1573
            Self::Text => Box::new(arrow::array::StringBuilder::with_capacity(len, 0)),
398✔
1574
            Self::Float => Box::new(arrow::array::Float64Builder::with_capacity(len)),
373✔
1575
            Self::Int => Box::new(arrow::array::Int64Builder::with_capacity(len)),
118✔
1576
            Self::Category => Box::new(arrow::array::UInt8Builder::with_capacity(len)),
2✔
1577
            Self::Bool => Box::new(arrow::array::BooleanBuilder::with_capacity(len)),
4✔
1578
            Self::DateTime => Box::new(arrow::array::Date64Builder::with_capacity(len)),
4✔
1579
        }
1580
    }
899✔
1581
}
1582

1583
impl FeatureData {
1584
    pub fn arrow_data_type(&self) -> arrow::datatypes::DataType {
426✔
1585
        FeatureDataType::from(self).arrow_data_type()
426✔
1586
    }
426✔
1587

1588
    pub fn nullable(&self) -> bool {
426✔
1589
        FeatureDataType::from(self).nullable()
426✔
1590
    }
426✔
1591

1592
    pub fn len(&self) -> usize {
443✔
1593
        match self {
443✔
1594
            FeatureData::Text(v) => v.len(),
72✔
1595
            FeatureData::NullableText(v) => v.len(),
84✔
1596
            FeatureData::Float(v) => v.len(),
51✔
1597
            FeatureData::NullableFloat(v) => v.len(),
77✔
1598
            FeatureData::Int(v) => v.len(),
91✔
1599
            FeatureData::NullableInt(v) => v.len(),
56✔
1600
            FeatureData::Category(v) => v.len(),
×
1601
            FeatureData::NullableCategory(v) => v.len(),
2✔
1602
            FeatureData::Bool(v) => v.len(),
2✔
1603
            FeatureData::NullableBool(v) => v.len(),
3✔
1604
            FeatureData::DateTime(v) => v.len(),
2✔
1605
            FeatureData::NullableDateTime(v) => v.len(),
3✔
1606
        }
1607
    }
443✔
1608

1609
    pub fn is_empty(&self) -> bool {
×
1610
        self.len() == 0
×
1611
    }
×
1612

1613
    /// Creates an `arrow` array builder.
1614
    pub(crate) fn arrow_builder(&self) -> Box<dyn arrow::array::ArrayBuilder> {
426✔
1615
        match self {
426✔
1616
            Self::Text(v) => {
72✔
1617
                let mut builder = arrow::array::StringBuilder::with_capacity(
72✔
1618
                    v.len(),
72✔
1619
                    v.iter().map(String::len).sum(),
72✔
1620
                );
72✔
1621
                for text in v {
225✔
1622
                    builder.append_value(text);
153✔
1623
                }
153✔
1624
                Box::new(builder)
72✔
1625
            }
1626
            Self::NullableText(v) => {
84✔
1627
                let mut builder = arrow::array::StringBuilder::with_capacity(
84✔
1628
                    v.len(),
84✔
1629
                    v.iter()
84✔
1630
                        .map(|text_option| text_option.as_ref().map_or(0, String::len))
199✔
1631
                        .sum(),
84✔
1632
                );
84✔
1633
                for text_opt in v {
283✔
1634
                    if let Some(text) = text_opt {
199✔
1635
                        builder.append_value(text);
134✔
1636
                    } else {
134✔
1637
                        builder.append_null();
65✔
1638
                    }
65✔
1639
                }
1640
                Box::new(builder)
84✔
1641
            }
1642
            Self::Float(v) => {
51✔
1643
                let mut builder = arrow::array::Float64Builder::with_capacity(v.len());
51✔
1644
                builder.append_slice(v);
51✔
1645
                Box::new(builder)
51✔
1646
            }
1647
            Self::NullableFloat(v) => {
70✔
1648
                let mut builder = arrow::array::Float64Builder::with_capacity(v.len());
70✔
1649
                for &number_option in v {
402✔
1650
                    builder.append_option(number_option);
332✔
1651
                }
332✔
1652
                Box::new(builder)
70✔
1653
            }
1654
            Self::Int(v) => {
91✔
1655
                let mut builder = arrow::array::Int64Builder::with_capacity(v.len());
91✔
1656
                builder.append_slice(v);
91✔
1657
                Box::new(builder)
91✔
1658
            }
1659
            Self::NullableInt(v) => {
46✔
1660
                let mut builder = arrow::array::Int64Builder::with_capacity(v.len());
46✔
1661
                for &int_option in v {
172✔
1662
                    builder.append_option(int_option);
126✔
1663
                }
126✔
1664
                Box::new(builder)
46✔
1665
            }
1666
            Self::Category(v) => {
×
1667
                let mut builder = arrow::array::UInt8Builder::with_capacity(v.len());
×
1668
                builder.append_slice(v);
×
1669
                Box::new(builder)
×
1670
            }
1671
            Self::NullableCategory(v) => {
2✔
1672
                let mut builder = arrow::array::UInt8Builder::with_capacity(v.len());
2✔
1673
                for &float_option in v {
8✔
1674
                    builder.append_option(float_option);
6✔
1675
                }
6✔
1676
                Box::new(builder)
2✔
1677
            }
1678
            FeatureData::Bool(v) => {
2✔
1679
                let mut builder = arrow::array::BooleanBuilder::with_capacity(v.len());
2✔
1680
                builder.append_slice(v);
2✔
1681
                Box::new(builder)
2✔
1682
            }
1683
            FeatureData::NullableBool(v) => {
3✔
1684
                let mut builder = arrow::array::BooleanBuilder::with_capacity(v.len());
3✔
1685
                for &bool_option in v {
12✔
1686
                    builder.append_option(bool_option);
9✔
1687
                }
9✔
1688
                Box::new(builder)
3✔
1689
            }
1690
            FeatureData::DateTime(v) => {
2✔
1691
                let mut builder = arrow::array::Date64Builder::with_capacity(v.len());
2✔
1692
                let x: Vec<_> = v.iter().map(|x| x.inner()).collect();
6✔
1693
                builder.append_slice(&x);
2✔
1694
                Box::new(builder)
2✔
1695
            }
1696
            FeatureData::NullableDateTime(v) => {
3✔
1697
                let mut builder = arrow::array::Date64Builder::with_capacity(v.len());
3✔
1698
                for &dt_option in v {
12✔
1699
                    builder.append_option(dt_option.map(TimeInstance::inner));
9✔
1700
                }
9✔
1701
                Box::new(builder)
3✔
1702
            }
1703
        }
1704
    }
426✔
1705
}
1706

1707
impl From<RasterDataType> for FeatureDataType {
1708
    fn from(value: RasterDataType) -> Self {
×
1709
        match value {
×
1710
            RasterDataType::U8
1711
            | RasterDataType::U16
1712
            | RasterDataType::U32
1713
            | RasterDataType::I8
1714
            | RasterDataType::I16
1715
            | RasterDataType::I32
1716
            | RasterDataType::U64
1717
            | RasterDataType::I64 => Self::Int,
×
1718
            RasterDataType::F32 | RasterDataType::F64 => Self::Float,
×
1719
        }
1720
    }
×
1721
}
1722

1723
impl From<&FeatureData> for FeatureDataType {
1724
    fn from(value: &FeatureData) -> Self {
1,278✔
1725
        match value {
1,278✔
1726
            FeatureData::Text(_) | FeatureData::NullableText(_) => Self::Text,
468✔
1727
            FeatureData::Float(_) | FeatureData::NullableFloat(_) => Self::Float,
363✔
1728
            FeatureData::Int(_) | FeatureData::NullableInt(_) => Self::Int,
411✔
1729
            FeatureData::Category(_) | FeatureData::NullableCategory(_) => Self::Category,
6✔
1730
            FeatureData::Bool(_) | FeatureData::NullableBool(_) => Self::Bool,
15✔
1731
            FeatureData::DateTime(_) | FeatureData::NullableDateTime(_) => Self::DateTime,
15✔
1732
        }
1733
    }
1,278✔
1734
}
1735

1736
impl From<&FeatureDataValue> for FeatureDataType {
1737
    fn from(value: &FeatureDataValue) -> Self {
15,918✔
1738
        match value {
15,918✔
1739
            FeatureDataValue::Text(_) | FeatureDataValue::NullableText(_) => Self::Text,
9,967✔
1740
            FeatureDataValue::Float(_) | FeatureDataValue::NullableFloat(_) => Self::Float,
5,683✔
1741
            FeatureDataValue::Int(_) | FeatureDataValue::NullableInt(_) => Self::Int,
174✔
1742
            FeatureDataValue::Category(_) | FeatureDataValue::NullableCategory(_) => Self::Category,
30✔
1743
            FeatureDataValue::Bool(_) | FeatureDataValue::NullableBool(_) => Self::Bool,
33✔
1744
            FeatureDataValue::DateTime(_) | FeatureDataValue::NullableDateTime(_) => Self::DateTime,
31✔
1745
        }
1746
    }
15,918✔
1747
}
1748

1749
impl<'f> From<&'f FeatureDataRef<'f>> for FeatureDataType {
1750
    fn from(value: &FeatureDataRef) -> Self {
×
1751
        match value {
×
1752
            FeatureDataRef::Text(_) => Self::Text,
×
1753
            FeatureDataRef::Float(..) => Self::Float,
×
1754
            FeatureDataRef::Int(_) => Self::Int,
×
1755
            FeatureDataRef::Category(_) => Self::Category,
×
1756
            FeatureDataRef::Bool(_) => Self::Bool,
×
1757
            FeatureDataRef::DateTime(_) => Self::DateTime,
×
1758
        }
1759
    }
×
1760
}
1761

1762
impl TryFrom<&FeatureDataValue> for f64 {
1763
    type Error = crate::collections::FeatureCollectionError;
1764

1765
    fn try_from(value: &FeatureDataValue) -> Result<Self, Self::Error> {
×
1766
        Ok(match value {
×
1767
            FeatureDataValue::Float(v) | FeatureDataValue::NullableFloat(Some(v)) => *v,
×
1768
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1769
        })
1770
    }
×
1771
}
1772

1773
impl TryFrom<FeatureDataValue> for f64 {
1774
    type Error = crate::collections::FeatureCollectionError;
1775

1776
    fn try_from(value: FeatureDataValue) -> Result<Self, Self::Error> {
×
1777
        f64::try_from(&value)
×
1778
    }
×
1779
}
1780

1781
impl TryFrom<&FeatureDataValue> for i64 {
1782
    type Error = crate::collections::FeatureCollectionError;
1783

1784
    fn try_from(value: &FeatureDataValue) -> Result<i64, Self::Error> {
×
1785
        Ok(match value {
×
1786
            FeatureDataValue::Int(v) | FeatureDataValue::NullableInt(Some(v)) => *v,
×
1787
            FeatureDataValue::DateTime(v) | FeatureDataValue::NullableDateTime(Some(v)) => {
×
1788
                v.inner()
×
1789
            }
1790
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1791
        })
1792
    }
×
1793
}
1794

1795
impl TryFrom<FeatureDataValue> for i64 {
1796
    type Error = crate::collections::FeatureCollectionError;
1797

1798
    fn try_from(value: FeatureDataValue) -> Result<i64, Self::Error> {
×
1799
        i64::try_from(&value)
×
1800
    }
×
1801
}
1802

1803
impl<'s> TryFrom<&'s FeatureDataValue> for &'s str {
1804
    type Error = crate::collections::FeatureCollectionError;
1805

1806
    fn try_from(value: &FeatureDataValue) -> Result<&str, Self::Error> {
×
1807
        Ok(match value {
×
1808
            FeatureDataValue::Text(v) | FeatureDataValue::NullableText(Some(v)) => v.as_ref(),
×
1809
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1810
        })
1811
    }
×
1812
}
1813

1814
impl TryFrom<&FeatureDataValue> for bool {
1815
    type Error = crate::collections::FeatureCollectionError;
1816

1817
    fn try_from(value: &FeatureDataValue) -> Result<bool, Self::Error> {
×
1818
        Ok(match value {
×
1819
            FeatureDataValue::Bool(v) | FeatureDataValue::NullableBool(Some(v)) => *v,
×
1820
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1821
        })
1822
    }
×
1823
}
1824

1825
impl TryFrom<&FeatureDataValue> for TimeInstance {
1826
    type Error = crate::collections::FeatureCollectionError;
1827

1828
    fn try_from(value: &FeatureDataValue) -> Result<TimeInstance, Self::Error> {
×
1829
        Ok(match value {
×
1830
            FeatureDataValue::DateTime(v) | FeatureDataValue::NullableDateTime(Some(v)) => *v,
×
1831
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1832
        })
1833
    }
×
1834
}
1835

1836
impl TryFrom<&FeatureDataValue> for arrow_array::Scalar<Float64Array> {
1837
    type Error = crate::collections::FeatureCollectionError;
1838

1839
    fn try_from(
3✔
1840
        value: &FeatureDataValue,
3✔
1841
    ) -> Result<arrow_array::Scalar<Float64Array>, Self::Error> {
3✔
1842
        Ok(match value {
×
1843
            FeatureDataValue::Float(v) | FeatureDataValue::NullableFloat(Some(v)) => {
3✔
1844
                Float64Array::new_scalar(*v)
3✔
1845
            }
1846
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1847
        })
1848
    }
3✔
1849
}
1850

1851
impl TryFrom<&FeatureDataValue> for arrow_array::Scalar<Int64Array> {
1852
    type Error = crate::collections::FeatureCollectionError;
1853

1854
    fn try_from(value: &FeatureDataValue) -> Result<arrow_array::Scalar<Int64Array>, Self::Error> {
12✔
1855
        Ok(match value {
×
1856
            FeatureDataValue::Int(v) | FeatureDataValue::NullableInt(Some(v)) => {
12✔
1857
                Int64Array::new_scalar(*v)
12✔
1858
            }
1859
            FeatureDataValue::DateTime(v) | FeatureDataValue::NullableDateTime(Some(v)) => {
×
1860
                Int64Array::new_scalar(v.inner())
×
1861
            }
1862
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1863
        })
1864
    }
12✔
1865
}
1866

1867
impl TryFrom<&FeatureDataValue> for arrow_array::Scalar<Date64Array> {
1868
    type Error = crate::collections::FeatureCollectionError;
1869

1870
    fn try_from(value: &FeatureDataValue) -> Result<arrow_array::Scalar<Date64Array>, Self::Error> {
1✔
1871
        Ok(match value {
×
1872
            FeatureDataValue::DateTime(v) | FeatureDataValue::NullableDateTime(Some(v)) => {
1✔
1873
                Date64Array::new_scalar(v.inner())
1✔
1874
            }
1875
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1876
        })
1877
    }
1✔
1878
}
1879

1880
impl TryFrom<&FeatureDataValue> for arrow_array::Scalar<StringArray> {
1881
    type Error = crate::collections::FeatureCollectionError;
1882

1883
    fn try_from(value: &FeatureDataValue) -> Result<arrow_array::Scalar<StringArray>, Self::Error> {
1✔
1884
        Ok(match value {
×
1885
            FeatureDataValue::Text(v) | FeatureDataValue::NullableText(Some(v)) => {
1✔
1886
                StringArray::new_scalar(v.clone())
1✔
1887
            }
1888
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1889
        })
1890
    }
1✔
1891
}
1892

1893
impl TryFrom<&FeatureDataValue> for arrow_array::Scalar<BooleanArray> {
1894
    type Error = crate::collections::FeatureCollectionError;
1895

1896
    fn try_from(
1✔
1897
        value: &FeatureDataValue,
1✔
1898
    ) -> Result<arrow_array::Scalar<BooleanArray>, Self::Error> {
1✔
1899
        Ok(match value {
×
1900
            FeatureDataValue::Bool(v) | FeatureDataValue::NullableBool(Some(v)) => {
1✔
1901
                BooleanArray::new_scalar(*v)
1✔
1902
            }
1903
            _ => return Err(crate::collections::FeatureCollectionError::WrongDataType),
×
1904
        })
1905
    }
1✔
1906
}
1907

1908
#[cfg(test)]
1909
mod tests {
1910
    use float_cmp::assert_approx_eq;
1911

1912
    use crate::{
1913
        collections::{DataCollection, FeatureCollectionInfos},
1914
        primitives::{NoGeometry, TimeInterval},
1915
    };
1916

1917
    use super::*;
1918

1919
    #[test]
1920
    fn strings_iter() {
1✔
1921
        let collection = DataCollection::from_slices(
1✔
1922
            &[] as &[NoGeometry],
1✔
1923
            &[TimeInterval::default(); 3],
1✔
1924
            &[
1✔
1925
                ("ints", FeatureData::Int(vec![1, 2, 3])),
1✔
1926
                (
1✔
1927
                    "floats",
1✔
1928
                    FeatureData::NullableFloat(vec![Some(1.0), None, Some(3.0)]),
1✔
1929
                ),
1✔
1930
                (
1✔
1931
                    "texts",
1✔
1932
                    FeatureData::NullableText(vec![
1✔
1933
                        Some("a".to_owned()),
1✔
1934
                        Some("b".to_owned()),
1✔
1935
                        None,
1✔
1936
                    ]),
1✔
1937
                ),
1✔
1938
                (
1✔
1939
                    "bools",
1✔
1940
                    FeatureData::NullableBool(vec![Some(true), Some(false), None]),
1✔
1941
                ),
1✔
1942
                (
1✔
1943
                    "dates",
1✔
1944
                    FeatureData::NullableDateTime(vec![
1✔
1945
                        Some(TimeInstance::from_millis_unchecked(946_681_200_000)),
1✔
1946
                        None,
1✔
1947
                        Some(TimeInstance::from_millis_unchecked(1_636_448_729_000)),
1✔
1948
                    ]),
1✔
1949
                ),
1✔
1950
            ],
1✔
1951
        )
1✔
1952
        .unwrap();
1✔
1953

1✔
1954
        let from_ints: Vec<String> = collection.data("ints").unwrap().strings_iter().collect();
1✔
1955
        let from_ints_cmp: Vec<String> = ["1", "2", "3"].iter().map(ToString::to_string).collect();
1✔
1956
        assert_eq!(from_ints, from_ints_cmp);
1✔
1957

1958
        let from_floats: Vec<String> = collection.data("floats").unwrap().strings_iter().collect();
1✔
1959
        let from_floats_cmp: Vec<String> = ["1", "", "3"].iter().map(ToString::to_string).collect();
1✔
1960
        assert_eq!(from_floats, from_floats_cmp);
1✔
1961

1962
        let from_strings: Vec<String> = collection.data("texts").unwrap().strings_iter().collect();
1✔
1963
        let from_strings_cmp: Vec<String> =
1✔
1964
            ["a", "b", ""].iter().map(ToString::to_string).collect();
1✔
1965
        assert_eq!(from_strings, from_strings_cmp);
1✔
1966

1967
        let from_bools: Vec<String> = collection.data("bools").unwrap().strings_iter().collect();
1✔
1968
        let from_bools_cmp: Vec<String> = ["true", "false", ""]
1✔
1969
            .iter()
1✔
1970
            .map(ToString::to_string)
1✔
1971
            .collect();
1✔
1972
        assert_eq!(from_bools, from_bools_cmp);
1✔
1973

1974
        let from_dates: Vec<String> = collection.data("dates").unwrap().strings_iter().collect();
1✔
1975
        let from_dates_cmp: Vec<String> =
1✔
1976
            ["1999-12-31T23:00:00.000Z", "", "2021-11-09T09:05:29.000Z"]
1✔
1977
                .iter()
1✔
1978
                .map(ToString::to_string)
1✔
1979
                .collect();
1✔
1980
        assert_eq!(from_dates, from_dates_cmp);
1✔
1981
    }
1✔
1982

1983
    #[test]
1984
    fn float_options_iter() {
1✔
1985
        let collection = DataCollection::from_slices(
1✔
1986
            &[] as &[NoGeometry],
1✔
1987
            &[TimeInterval::default(); 3],
1✔
1988
            &[
1✔
1989
                ("ints", FeatureData::Int(vec![1, 2, 3])),
1✔
1990
                (
1✔
1991
                    "floats",
1✔
1992
                    FeatureData::NullableFloat(vec![Some(1.0), None, Some(3.0)]),
1✔
1993
                ),
1✔
1994
                (
1✔
1995
                    "texts",
1✔
1996
                    FeatureData::NullableText(vec![
1✔
1997
                        Some("1".to_owned()),
1✔
1998
                        Some("f".to_owned()),
1✔
1999
                        None,
1✔
2000
                    ]),
1✔
2001
                ),
1✔
2002
                (
1✔
2003
                    "bools",
1✔
2004
                    FeatureData::NullableBool(vec![Some(true), Some(false), None]),
1✔
2005
                ),
1✔
2006
                (
1✔
2007
                    "dates",
1✔
2008
                    FeatureData::NullableDateTime(vec![
1✔
2009
                        Some(TimeInstance::from_millis_unchecked(946_681_200_000)),
1✔
2010
                        None,
1✔
2011
                        Some(TimeInstance::from_millis_unchecked(1_636_448_729_000)),
1✔
2012
                    ]),
1✔
2013
                ),
1✔
2014
                (
1✔
2015
                    "categories",
1✔
2016
                    FeatureData::NullableCategory(vec![Some(1), None, Some(3)]),
1✔
2017
                ),
1✔
2018
            ],
1✔
2019
        )
1✔
2020
        .unwrap();
1✔
2021

2022
        for (column, mut expected_vec_result) in [
6✔
2023
            ("ints", vec![Some(1.), Some(2.), Some(3.)]),
1✔
2024
            ("floats", vec![Some(1.), None, Some(3.)]),
1✔
2025
            ("texts", vec![Some(1.), None, None]),
1✔
2026
            ("bools", vec![Some(1.), Some(0.), None]),
1✔
2027
            (
1✔
2028
                "dates",
1✔
2029
                vec![Some(946_681_200_000.0), None, Some(1_636_448_729_000.0)],
1✔
2030
            ),
1✔
2031
            ("categories", vec![Some(1.), None, Some(3.)]),
1✔
2032
        ] {
2033
            let data_ref = collection.data(column).unwrap();
6✔
2034
            assert_eq!(
6✔
2035
                data_ref.float_options_iter().collect::<Vec<_>>(),
6✔
2036
                expected_vec_result
6✔
2037
            );
6✔
2038
            assert_eq!(
6✔
2039
                data_ref.float_options_iter().len(),
6✔
2040
                expected_vec_result.len()
6✔
2041
            );
6✔
2042
            expected_vec_result.reverse();
6✔
2043
            assert_eq!(
6✔
2044
                data_ref
6✔
2045
                    .float_options_iter()
6✔
2046
                    .rfold(Vec::new(), |mut acc, x| {
18✔
2047
                        acc.push(x);
18✔
2048
                        acc
18✔
2049
                    }),
18✔
2050
                expected_vec_result
6✔
2051
            );
6✔
2052
        }
2053
    }
1✔
2054

2055
    #[test]
2056
    fn float_options_par_iter() {
1✔
2057
        let collection = DataCollection::from_slices(
1✔
2058
            &[] as &[NoGeometry],
1✔
2059
            &[TimeInterval::default(); 3],
1✔
2060
            &[
1✔
2061
                ("ints", FeatureData::Int(vec![1, 2, 3])),
1✔
2062
                (
1✔
2063
                    "floats",
1✔
2064
                    FeatureData::NullableFloat(vec![Some(1.0), None, Some(3.0)]),
1✔
2065
                ),
1✔
2066
                (
1✔
2067
                    "texts",
1✔
2068
                    FeatureData::NullableText(vec![
1✔
2069
                        Some("1".to_owned()),
1✔
2070
                        Some("f".to_owned()),
1✔
2071
                        None,
1✔
2072
                    ]),
1✔
2073
                ),
1✔
2074
                (
1✔
2075
                    "bools",
1✔
2076
                    FeatureData::NullableBool(vec![Some(true), Some(false), None]),
1✔
2077
                ),
1✔
2078
                (
1✔
2079
                    "dates",
1✔
2080
                    FeatureData::NullableDateTime(vec![
1✔
2081
                        Some(TimeInstance::from_millis_unchecked(946_681_200_000)),
1✔
2082
                        None,
1✔
2083
                        Some(TimeInstance::from_millis_unchecked(1_636_448_729_000)),
1✔
2084
                    ]),
1✔
2085
                ),
1✔
2086
                (
1✔
2087
                    "categories",
1✔
2088
                    FeatureData::NullableCategory(vec![Some(1), None, Some(3)]),
1✔
2089
                ),
1✔
2090
            ],
1✔
2091
        )
1✔
2092
        .unwrap();
1✔
2093

2094
        for (column, vec_result, sum_result) in [
6✔
2095
            ("ints", vec![Some(1.), Some(2.), Some(3.)], 6.0),
1✔
2096
            ("floats", vec![Some(1.), None, Some(3.)], 4.0),
1✔
2097
            ("texts", vec![Some(1.), None, None], 1.0),
1✔
2098
            ("bools", vec![Some(1.), Some(0.), None], 1.0),
1✔
2099
            (
1✔
2100
                "dates",
1✔
2101
                vec![Some(946_681_200_000.0), None, Some(1_636_448_729_000.0)],
1✔
2102
                946_681_200_000. + 1_636_448_729_000.,
1✔
2103
            ),
1✔
2104
            ("categories", vec![Some(1.), None, Some(3.)], 4.),
1✔
2105
        ] {
2106
            let data = collection.data(column).unwrap();
6✔
2107
            let float_iter = data.float_options_par_iter();
6✔
2108
            assert_eq!(float_iter.len(), 3);
6✔
2109
            assert_eq!(
6✔
2110
                <[_; 2]>::from(float_iter.clone().split_at(1)).map(|d| d.len()),
12✔
2111
                [1, 2]
6✔
2112
            );
6✔
2113
            assert_eq!(float_iter.clone().collect::<Vec<_>>(), vec_result);
6✔
2114
            assert_approx_eq!(
6✔
2115
                f64,
6✔
2116
                float_iter.filter_map(std::convert::identity).sum::<f64>(),
6✔
2117
                sum_result
6✔
2118
            );
6✔
2119
        }
2120
    }
1✔
2121
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc