Coverage Report

Created: 2025-11-17 14:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/Users/andrewlamb/Software/arrow-rs/arrow-array/src/types.rs
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
//! Zero-sized types used to parameterize generic array implementations
19
20
use crate::delta::{
21
    add_days_datetime, add_months_datetime, shift_months, sub_days_datetime, sub_months_datetime,
22
};
23
use crate::temporal_conversions::as_datetime_with_timezone;
24
use crate::timezone::Tz;
25
use crate::{ArrowNativeTypeOp, OffsetSizeTrait};
26
use arrow_buffer::{Buffer, OffsetBuffer, i256};
27
use arrow_data::decimal::{
28
    format_decimal_str, is_validate_decimal_precision, is_validate_decimal32_precision,
29
    is_validate_decimal64_precision, is_validate_decimal256_precision, validate_decimal_precision,
30
    validate_decimal32_precision, validate_decimal64_precision, validate_decimal256_precision,
31
};
32
use arrow_data::{validate_binary_view, validate_string_view};
33
use arrow_schema::{
34
    ArrowError, DECIMAL_DEFAULT_SCALE, DECIMAL32_DEFAULT_SCALE, DECIMAL32_MAX_PRECISION,
35
    DECIMAL32_MAX_SCALE, DECIMAL64_DEFAULT_SCALE, DECIMAL64_MAX_PRECISION, DECIMAL64_MAX_SCALE,
36
    DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE, DECIMAL256_MAX_PRECISION, DECIMAL256_MAX_SCALE,
37
    DataType, IntervalUnit, TimeUnit,
38
};
39
use chrono::{Duration, NaiveDate, NaiveDateTime};
40
use half::f16;
41
use std::fmt::Debug;
42
use std::marker::PhantomData;
43
use std::ops::{Add, Sub};
44
45
// re-export types so that they can be used without importing arrow_buffer explicitly
46
pub use arrow_buffer::{IntervalDayTime, IntervalMonthDayNano};
47
48
// BooleanType is special: its bit-width is not the size of the primitive type, and its `index`
49
// operation assumes bit-packing.
50
/// A boolean datatype
51
#[derive(Debug)]
52
pub struct BooleanType {}
53
54
impl BooleanType {
55
    /// The corresponding Arrow data type
56
    pub const DATA_TYPE: DataType = DataType::Boolean;
57
}
58
59
/// Trait for [primitive values].
60
///
61
/// This trait bridges the dynamic-typed nature of Arrow
62
/// (via [`DataType`]) with the static-typed nature of rust types
63
/// ([`ArrowNativeType`]) for all types that implement [`ArrowNativeType`].
64
///
65
/// [primitive values]: https://arrow.apache.org/docs/format/Columnar.html#fixed-size-primitive-layout
66
/// [`ArrowNativeType`]: arrow_buffer::ArrowNativeType
67
pub trait ArrowPrimitiveType: primitive::PrimitiveTypeSealed + 'static {
68
    /// Corresponding Rust native type for the primitive type.
69
    type Native: ArrowNativeTypeOp;
70
71
    /// the corresponding Arrow data type of this primitive type.
72
    const DATA_TYPE: DataType;
73
74
    /// Returns a default value of this primitive type.
75
    ///
76
    /// This is useful for aggregate array ops like `sum()`, `mean()`.
77
17
    fn default_value() -> Self::Native {
78
17
        Default::default()
79
17
    }
80
}
81
82
mod primitive {
83
    pub trait PrimitiveTypeSealed {}
84
}
85
86
macro_rules! make_type {
87
    ($name:ident, $native_ty:ty, $data_ty:expr, $doc_string: literal) => {
88
        #[derive(Debug)]
89
        #[doc = $doc_string]
90
        pub struct $name {}
91
92
        impl ArrowPrimitiveType for $name {
93
            type Native = $native_ty;
94
            const DATA_TYPE: DataType = $data_ty;
95
        }
96
97
        impl primitive::PrimitiveTypeSealed for $name {}
98
    };
99
}
100
101
make_type!(Int8Type, i8, DataType::Int8, "A signed 8-bit integer type.");
102
make_type!(
103
    Int16Type,
104
    i16,
105
    DataType::Int16,
106
    "Signed 16-bit integer type."
107
);
108
make_type!(
109
    Int32Type,
110
    i32,
111
    DataType::Int32,
112
    "Signed 32-bit integer type."
113
);
114
make_type!(
115
    Int64Type,
116
    i64,
117
    DataType::Int64,
118
    "Signed 64-bit integer type."
119
);
120
make_type!(
121
    UInt8Type,
122
    u8,
123
    DataType::UInt8,
124
    "Unsigned 8-bit integer type."
125
);
126
make_type!(
127
    UInt16Type,
128
    u16,
129
    DataType::UInt16,
130
    "Unsigned 16-bit integer type."
131
);
132
make_type!(
133
    UInt32Type,
134
    u32,
135
    DataType::UInt32,
136
    "Unsigned 32-bit integer type."
137
);
138
make_type!(
139
    UInt64Type,
140
    u64,
141
    DataType::UInt64,
142
    "Unsigned 64-bit integer type."
143
);
144
make_type!(
145
    Float16Type,
146
    f16,
147
    DataType::Float16,
148
    "16-bit floating point number type."
149
);
150
make_type!(
151
    Float32Type,
152
    f32,
153
    DataType::Float32,
154
    "32-bit floating point number type."
155
);
156
make_type!(
157
    Float64Type,
158
    f64,
159
    DataType::Float64,
160
    "64-bit floating point number type."
161
);
162
make_type!(
163
    TimestampSecondType,
164
    i64,
165
    DataType::Timestamp(TimeUnit::Second, None),
166
    "Timestamp second type with an optional timezone."
167
);
168
make_type!(
169
    TimestampMillisecondType,
170
    i64,
171
    DataType::Timestamp(TimeUnit::Millisecond, None),
172
    "Timestamp millisecond type with an optional timezone."
173
);
174
make_type!(
175
    TimestampMicrosecondType,
176
    i64,
177
    DataType::Timestamp(TimeUnit::Microsecond, None),
178
    "Timestamp microsecond type with an optional timezone."
179
);
180
make_type!(
181
    TimestampNanosecondType,
182
    i64,
183
    DataType::Timestamp(TimeUnit::Nanosecond, None),
184
    "Timestamp nanosecond type with an optional timezone."
185
);
186
make_type!(
187
    Date32Type,
188
    i32,
189
    DataType::Date32,
190
    "32-bit date type: the elapsed time since UNIX epoch in days (32 bits)."
191
);
192
make_type!(
193
    Date64Type,
194
    i64,
195
    DataType::Date64,
196
    "64-bit date type: the elapsed time since UNIX epoch in milliseconds (64 bits). \
197
    Values must be divisible by `86_400_000`. \
198
    See [`DataType::Date64`] for more details."
199
);
200
make_type!(
201
    Time32SecondType,
202
    i32,
203
    DataType::Time32(TimeUnit::Second),
204
    "32-bit time type: the elapsed time since midnight in seconds."
205
);
206
make_type!(
207
    Time32MillisecondType,
208
    i32,
209
    DataType::Time32(TimeUnit::Millisecond),
210
    "32-bit time type: the elapsed time since midnight in milliseconds."
211
);
212
make_type!(
213
    Time64MicrosecondType,
214
    i64,
215
    DataType::Time64(TimeUnit::Microsecond),
216
    "64-bit time type: the elapsed time since midnight in microseconds."
217
);
218
make_type!(
219
    Time64NanosecondType,
220
    i64,
221
    DataType::Time64(TimeUnit::Nanosecond),
222
    "64-bit time type: the elapsed time since midnight in nanoseconds."
223
);
224
make_type!(
225
    IntervalYearMonthType,
226
    i32,
227
    DataType::Interval(IntervalUnit::YearMonth),
228
    "32-bit “calendar” interval type: the number of whole months."
229
);
230
make_type!(
231
    IntervalDayTimeType,
232
    IntervalDayTime,
233
    DataType::Interval(IntervalUnit::DayTime),
234
    "“Calendar” interval type: days and milliseconds. See [`IntervalDayTime`] for more details."
235
);
236
make_type!(
237
    IntervalMonthDayNanoType,
238
    IntervalMonthDayNano,
239
    DataType::Interval(IntervalUnit::MonthDayNano),
240
    r"“Calendar” interval type: months, days, and nanoseconds. See [`IntervalMonthDayNano`] for more details."
241
);
242
make_type!(
243
    DurationSecondType,
244
    i64,
245
    DataType::Duration(TimeUnit::Second),
246
    "Elapsed time type: seconds."
247
);
248
make_type!(
249
    DurationMillisecondType,
250
    i64,
251
    DataType::Duration(TimeUnit::Millisecond),
252
    "Elapsed time type: milliseconds."
253
);
254
make_type!(
255
    DurationMicrosecondType,
256
    i64,
257
    DataType::Duration(TimeUnit::Microsecond),
258
    "Elapsed time type: microseconds."
259
);
260
make_type!(
261
    DurationNanosecondType,
262
    i64,
263
    DataType::Duration(TimeUnit::Nanosecond),
264
    "Elapsed time type: nanoseconds."
265
);
266
267
/// A subtype of primitive type that represents legal dictionary keys.
268
/// See <https://arrow.apache.org/docs/format/Columnar.html>
269
pub trait ArrowDictionaryKeyType: ArrowPrimitiveType {}
270
271
impl ArrowDictionaryKeyType for Int8Type {}
272
273
impl ArrowDictionaryKeyType for Int16Type {}
274
275
impl ArrowDictionaryKeyType for Int32Type {}
276
277
impl ArrowDictionaryKeyType for Int64Type {}
278
279
impl ArrowDictionaryKeyType for UInt8Type {}
280
281
impl ArrowDictionaryKeyType for UInt16Type {}
282
283
impl ArrowDictionaryKeyType for UInt32Type {}
284
285
impl ArrowDictionaryKeyType for UInt64Type {}
286
287
/// A subtype of primitive type that is used as run-ends index
288
/// in `RunArray`.
289
/// See <https://arrow.apache.org/docs/format/Columnar.html>
290
pub trait RunEndIndexType: ArrowPrimitiveType {}
291
292
impl RunEndIndexType for Int16Type {}
293
294
impl RunEndIndexType for Int32Type {}
295
296
impl RunEndIndexType for Int64Type {}
297
298
/// A subtype of primitive type that represents temporal values.
299
pub trait ArrowTemporalType: ArrowPrimitiveType {}
300
301
impl ArrowTemporalType for TimestampSecondType {}
302
impl ArrowTemporalType for TimestampMillisecondType {}
303
impl ArrowTemporalType for TimestampMicrosecondType {}
304
impl ArrowTemporalType for TimestampNanosecondType {}
305
impl ArrowTemporalType for Date32Type {}
306
impl ArrowTemporalType for Date64Type {}
307
impl ArrowTemporalType for Time32SecondType {}
308
impl ArrowTemporalType for Time32MillisecondType {}
309
impl ArrowTemporalType for Time64MicrosecondType {}
310
impl ArrowTemporalType for Time64NanosecondType {}
311
// impl ArrowTemporalType for IntervalYearMonthType {}
312
// impl ArrowTemporalType for IntervalDayTimeType {}
313
// impl ArrowTemporalType for IntervalMonthDayNanoType {}
314
impl ArrowTemporalType for DurationSecondType {}
315
impl ArrowTemporalType for DurationMillisecondType {}
316
impl ArrowTemporalType for DurationMicrosecondType {}
317
impl ArrowTemporalType for DurationNanosecondType {}
318
319
/// A timestamp type allows us to create array builders that take a timestamp.
320
pub trait ArrowTimestampType: ArrowTemporalType<Native = i64> {
321
    /// The [`TimeUnit`] of this timestamp.
322
    const UNIT: TimeUnit;
323
324
    /// Creates a ArrowTimestampType::Native from the provided [`NaiveDateTime`]
325
    ///
326
    /// See [`DataType::Timestamp`] for more information on timezone handling
327
    fn make_value(naive: NaiveDateTime) -> Option<i64>;
328
}
329
330
impl ArrowTimestampType for TimestampSecondType {
331
    const UNIT: TimeUnit = TimeUnit::Second;
332
333
0
    fn make_value(naive: NaiveDateTime) -> Option<i64> {
334
0
        Some(naive.and_utc().timestamp())
335
0
    }
336
}
337
impl ArrowTimestampType for TimestampMillisecondType {
338
    const UNIT: TimeUnit = TimeUnit::Millisecond;
339
340
0
    fn make_value(naive: NaiveDateTime) -> Option<i64> {
341
0
        let utc = naive.and_utc();
342
0
        let millis = utc.timestamp().checked_mul(1_000)?;
343
0
        millis.checked_add(utc.timestamp_subsec_millis() as i64)
344
0
    }
345
}
346
impl ArrowTimestampType for TimestampMicrosecondType {
347
    const UNIT: TimeUnit = TimeUnit::Microsecond;
348
349
0
    fn make_value(naive: NaiveDateTime) -> Option<i64> {
350
0
        let utc = naive.and_utc();
351
0
        let micros = utc.timestamp().checked_mul(1_000_000)?;
352
0
        micros.checked_add(utc.timestamp_subsec_micros() as i64)
353
0
    }
354
}
355
impl ArrowTimestampType for TimestampNanosecondType {
356
    const UNIT: TimeUnit = TimeUnit::Nanosecond;
357
358
0
    fn make_value(naive: NaiveDateTime) -> Option<i64> {
359
0
        let utc = naive.and_utc();
360
0
        let nanos = utc.timestamp().checked_mul(1_000_000_000)?;
361
0
        nanos.checked_add(utc.timestamp_subsec_nanos() as i64)
362
0
    }
363
}
364
365
0
fn add_year_months<T: ArrowTimestampType>(
366
0
    timestamp: <T as ArrowPrimitiveType>::Native,
367
0
    delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
368
0
    tz: Tz,
369
0
) -> Option<<T as ArrowPrimitiveType>::Native> {
370
0
    let months = IntervalYearMonthType::to_months(delta);
371
0
    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
372
0
    let res = add_months_datetime(res, months)?;
373
0
    let res = res.naive_utc();
374
0
    T::make_value(res)
375
0
}
376
377
0
fn add_day_time<T: ArrowTimestampType>(
378
0
    timestamp: <T as ArrowPrimitiveType>::Native,
379
0
    delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
380
0
    tz: Tz,
381
0
) -> Option<<T as ArrowPrimitiveType>::Native> {
382
0
    let (days, ms) = IntervalDayTimeType::to_parts(delta);
383
0
    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
384
0
    let res = add_days_datetime(res, days)?;
385
0
    let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?;
386
0
    let res = res.naive_utc();
387
0
    T::make_value(res)
388
0
}
389
390
0
fn add_month_day_nano<T: ArrowTimestampType>(
391
0
    timestamp: <T as ArrowPrimitiveType>::Native,
392
0
    delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
393
0
    tz: Tz,
394
0
) -> Option<<T as ArrowPrimitiveType>::Native> {
395
0
    let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
396
0
    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
397
0
    let res = add_months_datetime(res, months)?;
398
0
    let res = add_days_datetime(res, days)?;
399
0
    let res = res.checked_add_signed(Duration::nanoseconds(nanos))?;
400
0
    let res = res.naive_utc();
401
0
    T::make_value(res)
402
0
}
403
404
0
fn subtract_year_months<T: ArrowTimestampType>(
405
0
    timestamp: <T as ArrowPrimitiveType>::Native,
406
0
    delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
407
0
    tz: Tz,
408
0
) -> Option<<T as ArrowPrimitiveType>::Native> {
409
0
    let months = IntervalYearMonthType::to_months(delta);
410
0
    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
411
0
    let res = sub_months_datetime(res, months)?;
412
0
    let res = res.naive_utc();
413
0
    T::make_value(res)
414
0
}
415
416
0
fn subtract_day_time<T: ArrowTimestampType>(
417
0
    timestamp: <T as ArrowPrimitiveType>::Native,
418
0
    delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
419
0
    tz: Tz,
420
0
) -> Option<<T as ArrowPrimitiveType>::Native> {
421
0
    let (days, ms) = IntervalDayTimeType::to_parts(delta);
422
0
    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
423
0
    let res = sub_days_datetime(res, days)?;
424
0
    let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?;
425
0
    let res = res.naive_utc();
426
0
    T::make_value(res)
427
0
}
428
429
0
fn subtract_month_day_nano<T: ArrowTimestampType>(
430
0
    timestamp: <T as ArrowPrimitiveType>::Native,
431
0
    delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
432
0
    tz: Tz,
433
0
) -> Option<<T as ArrowPrimitiveType>::Native> {
434
0
    let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
435
0
    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
436
0
    let res = sub_months_datetime(res, months)?;
437
0
    let res = sub_days_datetime(res, days)?;
438
0
    let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?;
439
0
    let res = res.naive_utc();
440
0
    T::make_value(res)
441
0
}
442
443
impl TimestampSecondType {
444
    /// Adds the given IntervalYearMonthType to an arrow TimestampSecondType.
445
    ///
446
    /// Returns `None` when it will result in overflow.
447
    ///
448
    /// # Arguments
449
    ///
450
    /// * `timestamp` - The date on which to perform the operation
451
    /// * `delta` - The interval to add
452
    /// * `tz` - The timezone in which to interpret `timestamp`
453
0
    pub fn add_year_months(
454
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
455
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
456
0
        tz: Tz,
457
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
458
0
        add_year_months::<Self>(timestamp, delta, tz)
459
0
    }
460
461
    /// Adds the given IntervalDayTimeType to an arrow TimestampSecondType.
462
    ///
463
    /// Returns `None` when it will result in overflow.
464
    ///
465
    /// # Arguments
466
    ///
467
    /// * `timestamp` - The date on which to perform the operation
468
    /// * `delta` - The interval to add
469
    /// * `tz` - The timezone in which to interpret `timestamp`
470
0
    pub fn add_day_time(
471
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
472
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
473
0
        tz: Tz,
474
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
475
0
        add_day_time::<Self>(timestamp, delta, tz)
476
0
    }
477
478
    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampSecondType
479
    ///
480
    /// Returns `None` when it will result in overflow.
481
    /// # Arguments
482
    ///
483
    /// * `timestamp` - The date on which to perform the operation
484
    /// * `delta` - The interval to add
485
    /// * `tz` - The timezone in which to interpret `timestamp`
486
0
    pub fn add_month_day_nano(
487
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
488
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
489
0
        tz: Tz,
490
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
491
0
        add_month_day_nano::<Self>(timestamp, delta, tz)
492
0
    }
493
494
    /// Subtracts the given IntervalYearMonthType to an arrow TimestampSecondType
495
    ///
496
    /// Returns `None` when it will result in overflow.
497
    ///
498
    /// # Arguments
499
    ///
500
    /// * `timestamp` - The date on which to perform the operation
501
    /// * `delta` - The interval to add
502
    /// * `tz` - The timezone in which to interpret `timestamp`
503
0
    pub fn subtract_year_months(
504
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
505
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
506
0
        tz: Tz,
507
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
508
0
        subtract_year_months::<Self>(timestamp, delta, tz)
509
0
    }
510
511
    /// Subtracts the given IntervalDayTimeType to an arrow TimestampSecondType
512
    ///
513
    /// Returns `None` when it will result in overflow.
514
    ///
515
    /// # Arguments
516
    ///
517
    /// * `timestamp` - The date on which to perform the operation
518
    /// * `delta` - The interval to add
519
    /// * `tz` - The timezone in which to interpret `timestamp`
520
0
    pub fn subtract_day_time(
521
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
522
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
523
0
        tz: Tz,
524
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
525
0
        subtract_day_time::<Self>(timestamp, delta, tz)
526
0
    }
527
528
    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampSecondType
529
    ///
530
    /// Returns `None` when it will result in overflow.
531
    ///
532
    /// # Arguments
533
    ///
534
    /// * `timestamp` - The date on which to perform the operation
535
    /// * `delta` - The interval to add
536
    /// * `tz` - The timezone in which to interpret `timestamp`
537
0
    pub fn subtract_month_day_nano(
538
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
539
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
540
0
        tz: Tz,
541
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
542
0
        subtract_month_day_nano::<Self>(timestamp, delta, tz)
543
0
    }
544
}
545
546
impl TimestampMicrosecondType {
547
    /// Adds the given IntervalYearMonthType to an arrow TimestampMicrosecondType
548
    ///
549
    /// # Arguments
550
    ///
551
    /// * `timestamp` - The date on which to perform the operation
552
    /// * `delta` - The interval to add
553
    /// * `tz` - The timezone in which to interpret `timestamp`
554
0
    pub fn add_year_months(
555
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
556
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
557
0
        tz: Tz,
558
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
559
0
        add_year_months::<Self>(timestamp, delta, tz)
560
0
    }
561
562
    /// Adds the given IntervalDayTimeType to an arrow TimestampMicrosecondType
563
    ///
564
    /// # Arguments
565
    ///
566
    /// * `timestamp` - The date on which to perform the operation
567
    /// * `delta` - The interval to add
568
    /// * `tz` - The timezone in which to interpret `timestamp`
569
0
    pub fn add_day_time(
570
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
571
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
572
0
        tz: Tz,
573
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
574
0
        add_day_time::<Self>(timestamp, delta, tz)
575
0
    }
576
577
    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampMicrosecondType
578
    ///
579
    /// # Arguments
580
    ///
581
    /// * `timestamp` - The date on which to perform the operation
582
    /// * `delta` - The interval to add
583
    /// * `tz` - The timezone in which to interpret `timestamp`
584
0
    pub fn add_month_day_nano(
585
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
586
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
587
0
        tz: Tz,
588
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
589
0
        add_month_day_nano::<Self>(timestamp, delta, tz)
590
0
    }
591
592
    /// Subtracts the given IntervalYearMonthType to an arrow TimestampMicrosecondType
593
    ///
594
    /// # Arguments
595
    ///
596
    /// * `timestamp` - The date on which to perform the operation
597
    /// * `delta` - The interval to add
598
    /// * `tz` - The timezone in which to interpret `timestamp`
599
0
    pub fn subtract_year_months(
600
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
601
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
602
0
        tz: Tz,
603
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
604
0
        subtract_year_months::<Self>(timestamp, delta, tz)
605
0
    }
606
607
    /// Subtracts the given IntervalDayTimeType to an arrow TimestampMicrosecondType
608
    ///
609
    /// # Arguments
610
    ///
611
    /// * `timestamp` - The date on which to perform the operation
612
    /// * `delta` - The interval to add
613
    /// * `tz` - The timezone in which to interpret `timestamp`
614
0
    pub fn subtract_day_time(
615
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
616
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
617
0
        tz: Tz,
618
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
619
0
        subtract_day_time::<Self>(timestamp, delta, tz)
620
0
    }
621
622
    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampMicrosecondType
623
    ///
624
    /// # Arguments
625
    ///
626
    /// * `timestamp` - The date on which to perform the operation
627
    /// * `delta` - The interval to add
628
    /// * `tz` - The timezone in which to interpret `timestamp`
629
0
    pub fn subtract_month_day_nano(
630
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
631
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
632
0
        tz: Tz,
633
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
634
0
        subtract_month_day_nano::<Self>(timestamp, delta, tz)
635
0
    }
636
}
637
638
impl TimestampMillisecondType {
639
    /// Adds the given IntervalYearMonthType to an arrow TimestampMillisecondType
640
    ///
641
    /// # Arguments
642
    ///
643
    /// * `timestamp` - The date on which to perform the operation
644
    /// * `delta` - The interval to add
645
    /// * `tz` - The timezone in which to interpret `timestamp`
646
0
    pub fn add_year_months(
647
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
648
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
649
0
        tz: Tz,
650
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
651
0
        add_year_months::<Self>(timestamp, delta, tz)
652
0
    }
653
654
    /// Adds the given IntervalDayTimeType to an arrow TimestampMillisecondType
655
    ///
656
    /// # Arguments
657
    ///
658
    /// * `timestamp` - The date on which to perform the operation
659
    /// * `delta` - The interval to add
660
    /// * `tz` - The timezone in which to interpret `timestamp`
661
0
    pub fn add_day_time(
662
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
663
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
664
0
        tz: Tz,
665
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
666
0
        add_day_time::<Self>(timestamp, delta, tz)
667
0
    }
668
669
    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampMillisecondType
670
    ///
671
    /// # Arguments
672
    ///
673
    /// * `timestamp` - The date on which to perform the operation
674
    /// * `delta` - The interval to add
675
    /// * `tz` - The timezone in which to interpret `timestamp`
676
0
    pub fn add_month_day_nano(
677
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
678
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
679
0
        tz: Tz,
680
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
681
0
        add_month_day_nano::<Self>(timestamp, delta, tz)
682
0
    }
683
684
    /// Subtracts the given IntervalYearMonthType to an arrow TimestampMillisecondType
685
    ///
686
    /// # Arguments
687
    ///
688
    /// * `timestamp` - The date on which to perform the operation
689
    /// * `delta` - The interval to add
690
    /// * `tz` - The timezone in which to interpret `timestamp`
691
0
    pub fn subtract_year_months(
692
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
693
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
694
0
        tz: Tz,
695
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
696
0
        subtract_year_months::<Self>(timestamp, delta, tz)
697
0
    }
698
699
    /// Subtracts the given IntervalDayTimeType to an arrow TimestampMillisecondType
700
    ///
701
    /// # Arguments
702
    ///
703
    /// * `timestamp` - The date on which to perform the operation
704
    /// * `delta` - The interval to add
705
    /// * `tz` - The timezone in which to interpret `timestamp`
706
0
    pub fn subtract_day_time(
707
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
708
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
709
0
        tz: Tz,
710
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
711
0
        subtract_day_time::<Self>(timestamp, delta, tz)
712
0
    }
713
714
    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampMillisecondType
715
    ///
716
    /// # Arguments
717
    ///
718
    /// * `timestamp` - The date on which to perform the operation
719
    /// * `delta` - The interval to add
720
    /// * `tz` - The timezone in which to interpret `timestamp`
721
0
    pub fn subtract_month_day_nano(
722
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
723
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
724
0
        tz: Tz,
725
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
726
0
        subtract_month_day_nano::<Self>(timestamp, delta, tz)
727
0
    }
728
}
729
730
impl TimestampNanosecondType {
731
    /// Adds the given IntervalYearMonthType to an arrow TimestampNanosecondType
732
    ///
733
    /// # Arguments
734
    ///
735
    /// * `timestamp` - The date on which to perform the operation
736
    /// * `delta` - The interval to add
737
    /// * `tz` - The timezone in which to interpret `timestamp`
738
0
    pub fn add_year_months(
739
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
740
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
741
0
        tz: Tz,
742
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
743
0
        add_year_months::<Self>(timestamp, delta, tz)
744
0
    }
745
746
    /// Adds the given IntervalDayTimeType to an arrow TimestampNanosecondType
747
    ///
748
    /// # Arguments
749
    ///
750
    /// * `timestamp` - The date on which to perform the operation
751
    /// * `delta` - The interval to add
752
    /// * `tz` - The timezone in which to interpret `timestamp`
753
0
    pub fn add_day_time(
754
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
755
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
756
0
        tz: Tz,
757
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
758
0
        add_day_time::<Self>(timestamp, delta, tz)
759
0
    }
760
761
    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType
762
    ///
763
    /// # Arguments
764
    ///
765
    /// * `timestamp` - The date on which to perform the operation
766
    /// * `delta` - The interval to add
767
    /// * `tz` - The timezone in which to interpret `timestamp`
768
0
    pub fn add_month_day_nano(
769
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
770
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
771
0
        tz: Tz,
772
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
773
0
        add_month_day_nano::<Self>(timestamp, delta, tz)
774
0
    }
775
776
    /// Subtracts the given IntervalYearMonthType to an arrow TimestampNanosecondType
777
    ///
778
    /// # Arguments
779
    ///
780
    /// * `timestamp` - The date on which to perform the operation
781
    /// * `delta` - The interval to add
782
    /// * `tz` - The timezone in which to interpret `timestamp`
783
0
    pub fn subtract_year_months(
784
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
785
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
786
0
        tz: Tz,
787
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
788
0
        subtract_year_months::<Self>(timestamp, delta, tz)
789
0
    }
790
791
    /// Subtracts the given IntervalDayTimeType to an arrow TimestampNanosecondType
792
    ///
793
    /// # Arguments
794
    ///
795
    /// * `timestamp` - The date on which to perform the operation
796
    /// * `delta` - The interval to add
797
    /// * `tz` - The timezone in which to interpret `timestamp`
798
0
    pub fn subtract_day_time(
799
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
800
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
801
0
        tz: Tz,
802
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
803
0
        subtract_day_time::<Self>(timestamp, delta, tz)
804
0
    }
805
806
    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType
807
    ///
808
    /// # Arguments
809
    ///
810
    /// * `timestamp` - The date on which to perform the operation
811
    /// * `delta` - The interval to add
812
    /// * `tz` - The timezone in which to interpret `timestamp`
813
0
    pub fn subtract_month_day_nano(
814
0
        timestamp: <Self as ArrowPrimitiveType>::Native,
815
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
816
0
        tz: Tz,
817
0
    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
818
0
        subtract_month_day_nano::<Self>(timestamp, delta, tz)
819
0
    }
820
}
821
822
impl IntervalYearMonthType {
823
    /// Creates a IntervalYearMonthType::Native
824
    ///
825
    /// # Arguments
826
    ///
827
    /// * `years` - The number of years (+/-) represented in this interval
828
    /// * `months` - The number of months (+/-) represented in this interval
829
    #[inline]
830
    pub fn make_value(
831
        years: i32,
832
        months: i32,
833
    ) -> <IntervalYearMonthType as ArrowPrimitiveType>::Native {
834
        years * 12 + months
835
    }
836
837
    /// Turns a IntervalYearMonthType type into an i32 of months.
838
    ///
839
    /// This operation is technically a no-op, it is included for comprehensiveness.
840
    ///
841
    /// # Arguments
842
    ///
843
    /// * `i` - The IntervalYearMonthType::Native to convert
844
    #[inline]
845
0
    pub fn to_months(i: <IntervalYearMonthType as ArrowPrimitiveType>::Native) -> i32 {
846
0
        i
847
0
    }
848
}
849
850
impl IntervalDayTimeType {
851
    /// Creates a IntervalDayTimeType::Native
852
    ///
853
    /// # Arguments
854
    ///
855
    /// * `days` - The number of days (+/-) represented in this interval
856
    /// * `millis` - The number of milliseconds (+/-) represented in this interval
857
    #[inline]
858
    pub fn make_value(days: i32, milliseconds: i32) -> IntervalDayTime {
859
        IntervalDayTime { days, milliseconds }
860
    }
861
862
    /// Turns a IntervalDayTimeType into a tuple of (days, milliseconds)
863
    ///
864
    /// # Arguments
865
    ///
866
    /// * `i` - The IntervalDayTimeType to convert
867
    #[inline]
868
0
    pub fn to_parts(i: IntervalDayTime) -> (i32, i32) {
869
0
        (i.days, i.milliseconds)
870
0
    }
871
}
872
873
impl IntervalMonthDayNanoType {
874
    /// Creates a IntervalMonthDayNanoType::Native
875
    ///
876
    /// # Arguments
877
    ///
878
    /// * `months` - The number of months (+/-) represented in this interval
879
    /// * `days` - The number of days (+/-) represented in this interval
880
    /// * `nanos` - The number of nanoseconds (+/-) represented in this interval
881
    #[inline]
882
    pub fn make_value(months: i32, days: i32, nanoseconds: i64) -> IntervalMonthDayNano {
883
        IntervalMonthDayNano {
884
            months,
885
            days,
886
            nanoseconds,
887
        }
888
    }
889
890
    /// Turns a IntervalMonthDayNanoType into a tuple of (months, days, nanos)
891
    ///
892
    /// # Arguments
893
    ///
894
    /// * `i` - The IntervalMonthDayNanoType to convert
895
    #[inline]
896
0
    pub fn to_parts(i: IntervalMonthDayNano) -> (i32, i32, i64) {
897
0
        (i.months, i.days, i.nanoseconds)
898
0
    }
899
}
900
901
impl Date32Type {
902
    /// Converts an arrow Date32Type into a chrono::NaiveDate
903
    ///
904
    /// # Arguments
905
    ///
906
    /// * `i` - The Date32Type to convert
907
0
    pub fn to_naive_date(i: <Date32Type as ArrowPrimitiveType>::Native) -> NaiveDate {
908
0
        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
909
0
        epoch.add(Duration::try_days(i as i64).unwrap())
910
0
    }
911
912
    /// Converts a chrono::NaiveDate into an arrow Date32Type
913
    ///
914
    /// # Arguments
915
    ///
916
    /// * `d` - The NaiveDate to convert
917
0
    pub fn from_naive_date(d: NaiveDate) -> <Date32Type as ArrowPrimitiveType>::Native {
918
0
        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
919
0
        d.sub(epoch).num_days() as <Date32Type as ArrowPrimitiveType>::Native
920
0
    }
921
922
    /// Adds the given IntervalYearMonthType to an arrow Date32Type
923
    ///
924
    /// # Arguments
925
    ///
926
    /// * `date` - The date on which to perform the operation
927
    /// * `delta` - The interval to add
928
0
    pub fn add_year_months(
929
0
        date: <Date32Type as ArrowPrimitiveType>::Native,
930
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
931
0
    ) -> <Date32Type as ArrowPrimitiveType>::Native {
932
0
        let prior = Date32Type::to_naive_date(date);
933
0
        let months = IntervalYearMonthType::to_months(delta);
934
0
        let posterior = shift_months(prior, months);
935
0
        Date32Type::from_naive_date(posterior)
936
0
    }
937
938
    /// Adds the given IntervalDayTimeType to an arrow Date32Type
939
    ///
940
    /// # Arguments
941
    ///
942
    /// * `date` - The date on which to perform the operation
943
    /// * `delta` - The interval to add
944
0
    pub fn add_day_time(
945
0
        date: <Date32Type as ArrowPrimitiveType>::Native,
946
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
947
0
    ) -> <Date32Type as ArrowPrimitiveType>::Native {
948
0
        let (days, ms) = IntervalDayTimeType::to_parts(delta);
949
0
        let res = Date32Type::to_naive_date(date);
950
0
        let res = res.add(Duration::try_days(days as i64).unwrap());
951
0
        let res = res.add(Duration::try_milliseconds(ms as i64).unwrap());
952
0
        Date32Type::from_naive_date(res)
953
0
    }
954
955
    /// Adds the given IntervalMonthDayNanoType to an arrow Date32Type
956
    ///
957
    /// # Arguments
958
    ///
959
    /// * `date` - The date on which to perform the operation
960
    /// * `delta` - The interval to add
961
0
    pub fn add_month_day_nano(
962
0
        date: <Date32Type as ArrowPrimitiveType>::Native,
963
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
964
0
    ) -> <Date32Type as ArrowPrimitiveType>::Native {
965
0
        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
966
0
        let res = Date32Type::to_naive_date(date);
967
0
        let res = shift_months(res, months);
968
0
        let res = res.add(Duration::try_days(days as i64).unwrap());
969
0
        let res = res.add(Duration::nanoseconds(nanos));
970
0
        Date32Type::from_naive_date(res)
971
0
    }
972
973
    /// Subtract the given IntervalYearMonthType to an arrow Date32Type
974
    ///
975
    /// # Arguments
976
    ///
977
    /// * `date` - The date on which to perform the operation
978
    /// * `delta` - The interval to subtract
979
0
    pub fn subtract_year_months(
980
0
        date: <Date32Type as ArrowPrimitiveType>::Native,
981
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
982
0
    ) -> <Date32Type as ArrowPrimitiveType>::Native {
983
0
        let prior = Date32Type::to_naive_date(date);
984
0
        let months = IntervalYearMonthType::to_months(-delta);
985
0
        let posterior = shift_months(prior, months);
986
0
        Date32Type::from_naive_date(posterior)
987
0
    }
988
989
    /// Subtract the given IntervalDayTimeType to an arrow Date32Type
990
    ///
991
    /// # Arguments
992
    ///
993
    /// * `date` - The date on which to perform the operation
994
    /// * `delta` - The interval to subtract
995
0
    pub fn subtract_day_time(
996
0
        date: <Date32Type as ArrowPrimitiveType>::Native,
997
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
998
0
    ) -> <Date32Type as ArrowPrimitiveType>::Native {
999
0
        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1000
0
        let res = Date32Type::to_naive_date(date);
1001
0
        let res = res.sub(Duration::try_days(days as i64).unwrap());
1002
0
        let res = res.sub(Duration::try_milliseconds(ms as i64).unwrap());
1003
0
        Date32Type::from_naive_date(res)
1004
0
    }
1005
1006
    /// Subtract the given IntervalMonthDayNanoType to an arrow Date32Type
1007
    ///
1008
    /// # Arguments
1009
    ///
1010
    /// * `date` - The date on which to perform the operation
1011
    /// * `delta` - The interval to subtract
1012
0
    pub fn subtract_month_day_nano(
1013
0
        date: <Date32Type as ArrowPrimitiveType>::Native,
1014
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1015
0
    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1016
0
        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1017
0
        let res = Date32Type::to_naive_date(date);
1018
0
        let res = shift_months(res, -months);
1019
0
        let res = res.sub(Duration::try_days(days as i64).unwrap());
1020
0
        let res = res.sub(Duration::nanoseconds(nanos));
1021
0
        Date32Type::from_naive_date(res)
1022
0
    }
1023
}
1024
1025
impl Date64Type {
1026
    /// Converts an arrow Date64Type into a chrono::NaiveDate
1027
    ///
1028
    /// # Arguments
1029
    ///
1030
    /// * `i` - The Date64Type to convert
1031
    #[deprecated(since = "56.0.0", note = "Use to_naive_date_opt instead.")]
1032
0
    pub fn to_naive_date(i: <Date64Type as ArrowPrimitiveType>::Native) -> NaiveDate {
1033
0
        Self::to_naive_date_opt(i)
1034
0
            .unwrap_or_else(|| panic!("Date64Type::to_naive_date overflowed for date: {i}",))
1035
0
    }
1036
1037
    /// Converts an arrow Date64Type into a chrono::NaiveDateTime if it fits in the range that chrono::NaiveDateTime can represent.
1038
    /// Returns `None` if the calculation would overflow or underflow.
1039
    ///
1040
    /// This function is able to handle dates ranging between 1677-09-21 (-9,223,372,800,000) and 2262-04-11 (9,223,286,400,000).
1041
    ///
1042
    /// # Arguments
1043
    ///
1044
    /// * `i` - The Date64Type to convert
1045
    ///
1046
    /// Returns `Some(NaiveDateTime)` if it fits, `None` otherwise.
1047
0
    pub fn to_naive_date_opt(i: <Date64Type as ArrowPrimitiveType>::Native) -> Option<NaiveDate> {
1048
0
        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1049
0
        Duration::try_milliseconds(i).and_then(|d| epoch.checked_add_signed(d))
1050
0
    }
1051
1052
    /// Converts a chrono::NaiveDate into an arrow Date64Type
1053
    ///
1054
    /// # Arguments
1055
    ///
1056
    /// * `d` - The NaiveDate to convert
1057
0
    pub fn from_naive_date(d: NaiveDate) -> <Date64Type as ArrowPrimitiveType>::Native {
1058
0
        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1059
0
        d.sub(epoch).num_milliseconds() as <Date64Type as ArrowPrimitiveType>::Native
1060
0
    }
1061
1062
    /// Adds the given IntervalYearMonthType to an arrow Date64Type
1063
    ///
1064
    /// # Arguments
1065
    ///
1066
    /// * `date` - The date on which to perform the operation
1067
    /// * `delta` - The interval to add
1068
    #[deprecated(
1069
        since = "56.0.0",
1070
        note = "Use `add_year_months_opt` instead, which returns an Option to handle overflow."
1071
    )]
1072
0
    pub fn add_year_months(
1073
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1074
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1075
0
    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1076
0
        Self::add_year_months_opt(date, delta).unwrap_or_else(|| {
1077
0
            panic!("Date64Type::add_year_months overflowed for date: {date}, delta: {delta}",)
1078
        })
1079
0
    }
1080
1081
    /// Adds the given IntervalYearMonthType to an arrow Date64Type
1082
    ///
1083
    /// # Arguments
1084
    ///
1085
    /// * `date` - The date on which to perform the operation
1086
    /// * `delta` - The interval to add
1087
    ///
1088
    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1089
0
    pub fn add_year_months_opt(
1090
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1091
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1092
0
    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1093
0
        let prior = Date64Type::to_naive_date_opt(date)?;
1094
0
        let months = IntervalYearMonthType::to_months(delta);
1095
0
        let posterior = shift_months(prior, months);
1096
0
        Some(Date64Type::from_naive_date(posterior))
1097
0
    }
1098
1099
    /// Adds the given IntervalDayTimeType to an arrow Date64Type
1100
    ///
1101
    /// # Arguments
1102
    ///
1103
    /// * `date` - The date on which to perform the operation
1104
    /// * `delta` - The interval to add
1105
    #[deprecated(
1106
        since = "56.0.0",
1107
        note = "Use `add_day_time_opt` instead, which returns an Option to handle overflow."
1108
    )]
1109
0
    pub fn add_day_time(
1110
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1111
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1112
0
    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1113
0
        Self::add_day_time_opt(date, delta).unwrap_or_else(|| {
1114
0
            panic!("Date64Type::add_day_time overflowed for date: {date}, delta: {delta:?}",)
1115
        })
1116
0
    }
1117
1118
    /// Adds the given IntervalDayTimeType to an arrow Date64Type
1119
    ///
1120
    /// # Arguments
1121
    ///
1122
    /// * `date` - The date on which to perform the operation
1123
    /// * `delta` - The interval to add
1124
    ///
1125
    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1126
0
    pub fn add_day_time_opt(
1127
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1128
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1129
0
    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1130
0
        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1131
0
        let res = Date64Type::to_naive_date_opt(date)?;
1132
0
        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1133
0
        let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?;
1134
0
        Some(Date64Type::from_naive_date(res))
1135
0
    }
1136
1137
    /// Adds the given IntervalMonthDayNanoType to an arrow Date64Type
1138
    ///
1139
    /// # Arguments
1140
    ///
1141
    /// * `date` - The date on which to perform the operation
1142
    /// * `delta` - The interval to add
1143
    #[deprecated(
1144
        since = "56.0.0",
1145
        note = "Use `add_month_day_nano_opt` instead, which returns an Option to handle overflow."
1146
    )]
1147
0
    pub fn add_month_day_nano(
1148
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1149
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1150
0
    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1151
0
        Self::add_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1152
0
            panic!("Date64Type::add_month_day_nano overflowed for date: {date}, delta: {delta:?}",)
1153
        })
1154
0
    }
1155
1156
    /// Adds the given IntervalMonthDayNanoType to an arrow Date64Type
1157
    ///
1158
    /// # Arguments
1159
    ///
1160
    /// * `date` - The date on which to perform the operation
1161
    /// * `delta` - The interval to add
1162
    ///
1163
    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1164
0
    pub fn add_month_day_nano_opt(
1165
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1166
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1167
0
    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1168
0
        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1169
0
        let res = Date64Type::to_naive_date_opt(date)?;
1170
0
        let res = shift_months(res, months);
1171
0
        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1172
0
        let res = res.checked_add_signed(Duration::nanoseconds(nanos))?;
1173
0
        Some(Date64Type::from_naive_date(res))
1174
0
    }
1175
1176
    /// Subtract the given IntervalYearMonthType to an arrow Date64Type
1177
    ///
1178
    /// # Arguments
1179
    ///
1180
    /// * `date` - The date on which to perform the operation
1181
    /// * `delta` - The interval to subtract
1182
    #[deprecated(
1183
        since = "56.0.0",
1184
        note = "Use `subtract_year_months_opt` instead, which returns an Option to handle overflow."
1185
    )]
1186
0
    pub fn subtract_year_months(
1187
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1188
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1189
0
    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1190
0
        Self::subtract_year_months_opt(date, delta).unwrap_or_else(|| {
1191
0
            panic!("Date64Type::subtract_year_months overflowed for date: {date}, delta: {delta}",)
1192
        })
1193
0
    }
1194
1195
    /// Subtract the given IntervalYearMonthType to an arrow Date64Type
1196
    ///
1197
    /// # Arguments
1198
    ///
1199
    /// * `date` - The date on which to perform the operation
1200
    /// * `delta` - The interval to subtract
1201
    ///
1202
    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1203
0
    pub fn subtract_year_months_opt(
1204
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1205
0
        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1206
0
    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1207
0
        let prior = Date64Type::to_naive_date_opt(date)?;
1208
0
        let months = IntervalYearMonthType::to_months(-delta);
1209
0
        let posterior = shift_months(prior, months);
1210
0
        Some(Date64Type::from_naive_date(posterior))
1211
0
    }
1212
1213
    /// Subtract the given IntervalDayTimeType to an arrow Date64Type
1214
    ///
1215
    /// # Arguments
1216
    ///
1217
    /// * `date` - The date on which to perform the operation
1218
    /// * `delta` - The interval to subtract
1219
    #[deprecated(
1220
        since = "56.0.0",
1221
        note = "Use `subtract_day_time_opt` instead, which returns an Option to handle overflow."
1222
    )]
1223
0
    pub fn subtract_day_time(
1224
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1225
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1226
0
    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1227
0
        Self::subtract_day_time_opt(date, delta).unwrap_or_else(|| {
1228
0
            panic!("Date64Type::subtract_day_time overflowed for date: {date}, delta: {delta:?}",)
1229
        })
1230
0
    }
1231
1232
    /// Subtract the given IntervalDayTimeType to an arrow Date64Type
1233
    ///
1234
    /// # Arguments
1235
    ///
1236
    /// * `date` - The date on which to perform the operation
1237
    /// * `delta` - The interval to subtract
1238
    ///
1239
    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1240
0
    pub fn subtract_day_time_opt(
1241
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1242
0
        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1243
0
    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1244
0
        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1245
0
        let res = Date64Type::to_naive_date_opt(date)?;
1246
0
        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1247
0
        let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?;
1248
0
        Some(Date64Type::from_naive_date(res))
1249
0
    }
1250
1251
    /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type
1252
    ///
1253
    /// # Arguments
1254
    ///
1255
    /// * `date` - The date on which to perform the operation
1256
    /// * `delta` - The interval to subtract
1257
    #[deprecated(
1258
        since = "56.0.0",
1259
        note = "Use `subtract_month_day_nano_opt` instead, which returns an Option to handle overflow."
1260
    )]
1261
0
    pub fn subtract_month_day_nano(
1262
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1263
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1264
0
    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1265
0
        Self::subtract_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1266
0
            panic!(
1267
0
                "Date64Type::subtract_month_day_nano overflowed for date: {date}, delta: {delta:?}",
1268
            )
1269
        })
1270
0
    }
1271
1272
    /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type
1273
    ///
1274
    /// # Arguments
1275
    ///
1276
    /// * `date` - The date on which to perform the operation
1277
    /// * `delta` - The interval to subtract
1278
    ///
1279
    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1280
0
    pub fn subtract_month_day_nano_opt(
1281
0
        date: <Date64Type as ArrowPrimitiveType>::Native,
1282
0
        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1283
0
    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1284
0
        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1285
0
        let res = Date64Type::to_naive_date_opt(date)?;
1286
0
        let res = shift_months(res, -months);
1287
0
        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1288
0
        let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?;
1289
0
        Some(Date64Type::from_naive_date(res))
1290
0
    }
1291
}
1292
1293
/// Crate private types for Decimal Arrays
1294
///
1295
/// Not intended to be used outside this crate
1296
mod decimal {
1297
    use super::*;
1298
1299
    pub trait DecimalTypeSealed {}
1300
    impl DecimalTypeSealed for Decimal32Type {}
1301
    impl DecimalTypeSealed for Decimal64Type {}
1302
    impl DecimalTypeSealed for Decimal128Type {}
1303
    impl DecimalTypeSealed for Decimal256Type {}
1304
}
1305
1306
/// A trait over the decimal types, used by [`PrimitiveArray`] to provide a generic
1307
/// implementation across the various decimal types
1308
///
1309
/// Implemented by [`Decimal32Type`], [`Decimal64Type`], [`Decimal128Type`] and [`Decimal256Type`]
1310
/// for [`Decimal32Array`], [`Decimal64Array`], [`Decimal128Array`] and [`Decimal256Array`] respectively
1311
///
1312
/// [`PrimitiveArray`]: crate::array::PrimitiveArray
1313
/// [`Decimal32Array`]: crate::array::Decimal32Array
1314
/// [`Decimal64Array`]: crate::array::Decimal64Array
1315
/// [`Decimal128Array`]: crate::array::Decimal128Array
1316
/// [`Decimal256Array`]: crate::array::Decimal256Array
1317
pub trait DecimalType:
1318
    'static + Send + Sync + ArrowPrimitiveType + decimal::DecimalTypeSealed
1319
{
1320
    /// Width of the type
1321
    const BYTE_LENGTH: usize;
1322
    /// Maximum number of significant digits
1323
    const MAX_PRECISION: u8;
1324
    /// Maximum no of digits after the decimal point (note the scale can be negative)
1325
    const MAX_SCALE: i8;
1326
    /// The maximum value for each precision in `0..=MAX_PRECISION`: [0, 9, 99, ...]
1327
    const MAX_FOR_EACH_PRECISION: &'static [Self::Native];
1328
    /// fn to create its [`DataType`]
1329
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType;
1330
    /// Default values for [`DataType`]
1331
    const DEFAULT_TYPE: DataType;
1332
1333
    /// "Decimal32", "Decimal64", "Decimal128" or "Decimal256", for use in error messages
1334
    const PREFIX: &'static str;
1335
1336
    /// Formats the decimal value with the provided precision and scale
1337
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String;
1338
1339
    /// Validates that `value` contains no more than `precision` decimal digits
1340
    fn validate_decimal_precision(
1341
        value: Self::Native,
1342
        precision: u8,
1343
        scale: i8,
1344
    ) -> Result<(), ArrowError>;
1345
1346
    /// Determines whether `value` contains no more than `precision` decimal digits
1347
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool;
1348
}
1349
1350
/// Validate that `precision` and `scale` are valid for `T`
1351
///
1352
/// Returns an Error if:
1353
/// - `precision` is zero
1354
/// - `precision` is larger than `T:MAX_PRECISION`
1355
/// - `scale` is larger than `T::MAX_SCALE`
1356
/// - `scale` is > `precision`
1357
5
pub fn validate_decimal_precision_and_scale<T: DecimalType>(
1358
5
    precision: u8,
1359
5
    scale: i8,
1360
5
) -> Result<(), ArrowError> {
1361
5
    if precision == 0 {
1362
0
        return Err(ArrowError::InvalidArgumentError(format!(
1363
0
            "precision cannot be 0, has to be between [1, {}]",
1364
0
            T::MAX_PRECISION
1365
0
        )));
1366
5
    }
1367
5
    if precision > T::MAX_PRECISION {
1368
0
        return Err(ArrowError::InvalidArgumentError(format!(
1369
0
            "precision {} is greater than max {}",
1370
0
            precision,
1371
0
            T::MAX_PRECISION
1372
0
        )));
1373
5
    }
1374
5
    if scale > T::MAX_SCALE {
1375
0
        return Err(ArrowError::InvalidArgumentError(format!(
1376
0
            "scale {} is greater than max {}",
1377
0
            scale,
1378
0
            T::MAX_SCALE
1379
0
        )));
1380
5
    }
1381
5
    if scale > 0 && scale as u8 > precision {
1382
0
        return Err(ArrowError::InvalidArgumentError(format!(
1383
0
            "scale {scale} is greater than precision {precision}"
1384
0
        )));
1385
5
    }
1386
1387
5
    Ok(())
1388
5
}
1389
1390
/// The decimal type for a Decimal32Array
1391
#[derive(Debug)]
1392
pub struct Decimal32Type {}
1393
1394
impl DecimalType for Decimal32Type {
1395
    const BYTE_LENGTH: usize = 4;
1396
    const MAX_PRECISION: u8 = DECIMAL32_MAX_PRECISION;
1397
    const MAX_SCALE: i8 = DECIMAL32_MAX_SCALE;
1398
    const MAX_FOR_EACH_PRECISION: &'static [i32] =
1399
        &arrow_data::decimal::MAX_DECIMAL32_FOR_EACH_PRECISION;
1400
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal32;
1401
    const DEFAULT_TYPE: DataType =
1402
        DataType::Decimal32(DECIMAL32_MAX_PRECISION, DECIMAL32_DEFAULT_SCALE);
1403
    const PREFIX: &'static str = "Decimal32";
1404
1405
0
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1406
0
        format_decimal_str(&value.to_string(), precision as usize, scale)
1407
0
    }
1408
1409
0
    fn validate_decimal_precision(num: i32, precision: u8, scale: i8) -> Result<(), ArrowError> {
1410
0
        validate_decimal32_precision(num, precision, scale)
1411
0
    }
1412
1413
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1414
0
        is_validate_decimal32_precision(value, precision)
1415
0
    }
1416
}
1417
1418
impl ArrowPrimitiveType for Decimal32Type {
1419
    type Native = i32;
1420
1421
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1422
}
1423
1424
impl primitive::PrimitiveTypeSealed for Decimal32Type {}
1425
1426
/// The decimal type for a Decimal64Array
1427
#[derive(Debug)]
1428
pub struct Decimal64Type {}
1429
1430
impl DecimalType for Decimal64Type {
1431
    const BYTE_LENGTH: usize = 8;
1432
    const MAX_PRECISION: u8 = DECIMAL64_MAX_PRECISION;
1433
    const MAX_SCALE: i8 = DECIMAL64_MAX_SCALE;
1434
    const MAX_FOR_EACH_PRECISION: &'static [i64] =
1435
        &arrow_data::decimal::MAX_DECIMAL64_FOR_EACH_PRECISION;
1436
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal64;
1437
    const DEFAULT_TYPE: DataType =
1438
        DataType::Decimal64(DECIMAL64_MAX_PRECISION, DECIMAL64_DEFAULT_SCALE);
1439
    const PREFIX: &'static str = "Decimal64";
1440
1441
0
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1442
0
        format_decimal_str(&value.to_string(), precision as usize, scale)
1443
0
    }
1444
1445
0
    fn validate_decimal_precision(num: i64, precision: u8, scale: i8) -> Result<(), ArrowError> {
1446
0
        validate_decimal64_precision(num, precision, scale)
1447
0
    }
1448
1449
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1450
0
        is_validate_decimal64_precision(value, precision)
1451
0
    }
1452
}
1453
1454
impl ArrowPrimitiveType for Decimal64Type {
1455
    type Native = i64;
1456
1457
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1458
}
1459
1460
impl primitive::PrimitiveTypeSealed for Decimal64Type {}
1461
1462
/// The decimal type for a Decimal128Array
1463
#[derive(Debug)]
1464
pub struct Decimal128Type {}
1465
1466
impl DecimalType for Decimal128Type {
1467
    const BYTE_LENGTH: usize = 16;
1468
    const MAX_PRECISION: u8 = DECIMAL128_MAX_PRECISION;
1469
    const MAX_SCALE: i8 = DECIMAL128_MAX_SCALE;
1470
    const MAX_FOR_EACH_PRECISION: &'static [i128] =
1471
        &arrow_data::decimal::MAX_DECIMAL128_FOR_EACH_PRECISION;
1472
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal128;
1473
    const DEFAULT_TYPE: DataType =
1474
        DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1475
    const PREFIX: &'static str = "Decimal128";
1476
1477
0
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1478
0
        format_decimal_str(&value.to_string(), precision as usize, scale)
1479
0
    }
1480
1481
0
    fn validate_decimal_precision(num: i128, precision: u8, scale: i8) -> Result<(), ArrowError> {
1482
0
        validate_decimal_precision(num, precision, scale)
1483
0
    }
1484
1485
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1486
0
        is_validate_decimal_precision(value, precision)
1487
0
    }
1488
}
1489
1490
impl ArrowPrimitiveType for Decimal128Type {
1491
    type Native = i128;
1492
1493
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1494
}
1495
1496
impl primitive::PrimitiveTypeSealed for Decimal128Type {}
1497
1498
/// The decimal type for a Decimal256Array
1499
#[derive(Debug)]
1500
pub struct Decimal256Type {}
1501
1502
impl DecimalType for Decimal256Type {
1503
    const BYTE_LENGTH: usize = 32;
1504
    const MAX_PRECISION: u8 = DECIMAL256_MAX_PRECISION;
1505
    const MAX_SCALE: i8 = DECIMAL256_MAX_SCALE;
1506
    const MAX_FOR_EACH_PRECISION: &'static [i256] =
1507
        &arrow_data::decimal::MAX_DECIMAL256_FOR_EACH_PRECISION;
1508
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal256;
1509
    const DEFAULT_TYPE: DataType =
1510
        DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1511
    const PREFIX: &'static str = "Decimal256";
1512
1513
0
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1514
0
        format_decimal_str(&value.to_string(), precision as usize, scale)
1515
0
    }
1516
1517
0
    fn validate_decimal_precision(num: i256, precision: u8, scale: i8) -> Result<(), ArrowError> {
1518
0
        validate_decimal256_precision(num, precision, scale)
1519
0
    }
1520
1521
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1522
0
        is_validate_decimal256_precision(value, precision)
1523
0
    }
1524
}
1525
1526
impl ArrowPrimitiveType for Decimal256Type {
1527
    type Native = i256;
1528
1529
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1530
}
1531
1532
impl primitive::PrimitiveTypeSealed for Decimal256Type {}
1533
1534
/// Crate private types for Byte Arrays
1535
///
1536
/// Not intended to be used outside this crate
1537
pub(crate) mod bytes {
1538
    use super::*;
1539
1540
    pub trait ByteArrayTypeSealed {}
1541
    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericStringType<O> {}
1542
    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericBinaryType<O> {}
1543
1544
    pub trait ByteArrayNativeType: std::fmt::Debug + Send + Sync {
1545
        fn from_bytes_checked(b: &[u8]) -> Option<&Self>;
1546
1547
        /// # Safety
1548
        ///
1549
        /// `b` must be a valid byte sequence for `Self`
1550
        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self;
1551
    }
1552
1553
    impl ByteArrayNativeType for [u8] {
1554
        #[inline]
1555
        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1556
            Some(b)
1557
        }
1558
1559
        #[inline]
1560
5
        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1561
5
            b
1562
5
        }
1563
    }
1564
1565
    impl ByteArrayNativeType for str {
1566
        #[inline]
1567
        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1568
            std::str::from_utf8(b).ok()
1569
        }
1570
1571
        #[inline]
1572
135k
        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1573
135k
            unsafe { std::str::from_utf8_unchecked(b) }
1574
135k
        }
1575
    }
1576
}
1577
1578
/// A trait over the variable-size byte array types
1579
///
1580
/// See [Variable Size Binary Layout](https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout)
1581
pub trait ByteArrayType: 'static + Send + Sync + bytes::ByteArrayTypeSealed {
1582
    /// Type of offset i.e i32/i64
1583
    type Offset: OffsetSizeTrait;
1584
    /// Type for representing its equivalent rust type i.e
1585
    /// Utf8Array will have native type has &str
1586
    /// BinaryArray will have type as [u8]
1587
    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1588
1589
    /// "Binary" or "String", for use in error messages
1590
    const PREFIX: &'static str;
1591
1592
    /// Datatype of array elements
1593
    const DATA_TYPE: DataType;
1594
1595
    /// Verifies that every consecutive pair of `offsets` denotes a valid slice of `values`
1596
    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError>;
1597
}
1598
1599
/// [`ByteArrayType`] for string arrays
1600
pub struct GenericStringType<O: OffsetSizeTrait> {
1601
    phantom: PhantomData<O>,
1602
}
1603
1604
impl<O: OffsetSizeTrait> ByteArrayType for GenericStringType<O> {
1605
    type Offset = O;
1606
    type Native = str;
1607
    const PREFIX: &'static str = "String";
1608
1609
    const DATA_TYPE: DataType = if O::IS_LARGE {
1610
        DataType::LargeUtf8
1611
    } else {
1612
        DataType::Utf8
1613
    };
1614
1615
1
    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1616
        // Verify that the slice as a whole is valid UTF-8
1617
1
        let validated = std::str::from_utf8(values).map_err(|e| 
{0
1618
0
            ArrowError::InvalidArgumentError(format!("Encountered non UTF-8 data: {e}"))
1619
0
        })?;
1620
1621
        // Verify each offset is at a valid character boundary in this UTF-8 array
1622
6
        for offset in 
offsets1
.
iter1
() {
1623
6
            let o = offset.as_usize();
1624
6
            if !validated.is_char_boundary(o) {
1625
0
                if o < validated.len() {
1626
0
                    return Err(ArrowError::InvalidArgumentError(format!(
1627
0
                        "Split UTF-8 codepoint at offset {o}"
1628
0
                    )));
1629
0
                }
1630
0
                return Err(ArrowError::InvalidArgumentError(format!(
1631
0
                    "Offset of {o} exceeds length of values {}",
1632
0
                    validated.len()
1633
0
                )));
1634
6
            }
1635
        }
1636
1
        Ok(())
1637
1
    }
1638
}
1639
1640
/// An arrow utf8 array with i32 offsets
1641
pub type Utf8Type = GenericStringType<i32>;
1642
/// An arrow utf8 array with i64 offsets
1643
pub type LargeUtf8Type = GenericStringType<i64>;
1644
1645
/// [`ByteArrayType`] for binary arrays
1646
pub struct GenericBinaryType<O: OffsetSizeTrait> {
1647
    phantom: PhantomData<O>,
1648
}
1649
1650
impl<O: OffsetSizeTrait> ByteArrayType for GenericBinaryType<O> {
1651
    type Offset = O;
1652
    type Native = [u8];
1653
    const PREFIX: &'static str = "Binary";
1654
1655
    const DATA_TYPE: DataType = if O::IS_LARGE {
1656
        DataType::LargeBinary
1657
    } else {
1658
        DataType::Binary
1659
    };
1660
1661
    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1662
        // offsets are guaranteed to be monotonically increasing and non-empty
1663
        let max_offset = offsets.last().unwrap().as_usize();
1664
        if values.len() < max_offset {
1665
            return Err(ArrowError::InvalidArgumentError(format!(
1666
                "Maximum offset of {max_offset} is larger than values of length {}",
1667
                values.len()
1668
            )));
1669
        }
1670
        Ok(())
1671
    }
1672
}
1673
1674
/// An arrow binary array with i32 offsets
1675
pub type BinaryType = GenericBinaryType<i32>;
1676
/// An arrow binary array with i64 offsets
1677
pub type LargeBinaryType = GenericBinaryType<i64>;
1678
1679
mod byte_view {
1680
    use crate::types::{BinaryViewType, StringViewType};
1681
1682
    pub trait Sealed: Send + Sync {}
1683
    impl Sealed for StringViewType {}
1684
    impl Sealed for BinaryViewType {}
1685
}
1686
1687
/// A trait over the variable length bytes view array types
1688
pub trait ByteViewType: byte_view::Sealed + 'static + PartialEq + Send + Sync {
1689
    /// If element in array is utf8 encoded string.
1690
    const IS_UTF8: bool;
1691
1692
    /// Datatype of array elements
1693
    const DATA_TYPE: DataType = if Self::IS_UTF8 {
1694
        DataType::Utf8View
1695
    } else {
1696
        DataType::BinaryView
1697
    };
1698
1699
    /// "Binary" or "String", for use in displayed or error messages
1700
    const PREFIX: &'static str;
1701
1702
    /// Type for representing its equivalent rust type i.e
1703
    /// Utf8Array will have native type has &str
1704
    /// BinaryArray will have type as [u8]
1705
    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1706
1707
    /// Type for owned corresponding to `Native`
1708
    type Owned: Debug + Clone + Sync + Send + AsRef<Self::Native>;
1709
1710
    /// Verifies that the provided buffers are valid for this array type
1711
    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError>;
1712
}
1713
1714
/// [`ByteViewType`] for string arrays
1715
#[derive(PartialEq)]
1716
pub struct StringViewType {}
1717
1718
impl ByteViewType for StringViewType {
1719
    const IS_UTF8: bool = true;
1720
    const PREFIX: &'static str = "String";
1721
1722
    type Native = str;
1723
    type Owned = String;
1724
1725
2
    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1726
2
        validate_string_view(views, buffers)
1727
2
    }
1728
}
1729
1730
/// [`BinaryViewType`] for string arrays
1731
#[derive(PartialEq)]
1732
pub struct BinaryViewType {}
1733
1734
impl ByteViewType for BinaryViewType {
1735
    const IS_UTF8: bool = false;
1736
    const PREFIX: &'static str = "Binary";
1737
    type Native = [u8];
1738
    type Owned = Vec<u8>;
1739
1740
0
    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1741
0
        validate_binary_view(views, buffers)
1742
0
    }
1743
}
1744
1745
#[cfg(test)]
1746
mod tests {
1747
    use super::*;
1748
    use arrow_data::{BufferSpec, layout};
1749
1750
    #[test]
1751
    fn month_day_nano_should_roundtrip() {
1752
        let value = IntervalMonthDayNanoType::make_value(1, 2, 3);
1753
        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (1, 2, 3));
1754
    }
1755
1756
    #[test]
1757
    fn month_day_nano_should_roundtrip_neg() {
1758
        let value = IntervalMonthDayNanoType::make_value(-1, -2, -3);
1759
        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (-1, -2, -3));
1760
    }
1761
1762
    #[test]
1763
    fn day_time_should_roundtrip() {
1764
        let value = IntervalDayTimeType::make_value(1, 2);
1765
        assert_eq!(IntervalDayTimeType::to_parts(value), (1, 2));
1766
    }
1767
1768
    #[test]
1769
    fn day_time_should_roundtrip_neg() {
1770
        let value = IntervalDayTimeType::make_value(-1, -2);
1771
        assert_eq!(IntervalDayTimeType::to_parts(value), (-1, -2));
1772
    }
1773
1774
    #[test]
1775
    fn year_month_should_roundtrip() {
1776
        let value = IntervalYearMonthType::make_value(1, 2);
1777
        assert_eq!(IntervalYearMonthType::to_months(value), 14);
1778
    }
1779
1780
    #[test]
1781
    fn year_month_should_roundtrip_neg() {
1782
        let value = IntervalYearMonthType::make_value(-1, -2);
1783
        assert_eq!(IntervalYearMonthType::to_months(value), -14);
1784
    }
1785
1786
    fn test_layout<T: ArrowPrimitiveType>() {
1787
        let layout = layout(&T::DATA_TYPE);
1788
1789
        assert_eq!(layout.buffers.len(), 1);
1790
1791
        let spec = &layout.buffers[0];
1792
        assert_eq!(
1793
            spec,
1794
            &BufferSpec::FixedWidth {
1795
                byte_width: std::mem::size_of::<T::Native>(),
1796
                alignment: std::mem::align_of::<T::Native>(),
1797
            }
1798
        );
1799
    }
1800
1801
    #[test]
1802
    fn test_layouts() {
1803
        test_layout::<Int8Type>();
1804
        test_layout::<Int16Type>();
1805
        test_layout::<Int32Type>();
1806
        test_layout::<Int64Type>();
1807
        test_layout::<UInt8Type>();
1808
        test_layout::<UInt16Type>();
1809
        test_layout::<UInt32Type>();
1810
        test_layout::<UInt64Type>();
1811
        test_layout::<Float16Type>();
1812
        test_layout::<Float32Type>();
1813
        test_layout::<Float64Type>();
1814
        test_layout::<Decimal32Type>();
1815
        test_layout::<Decimal64Type>();
1816
        test_layout::<Decimal128Type>();
1817
        test_layout::<Decimal256Type>();
1818
        test_layout::<TimestampNanosecondType>();
1819
        test_layout::<TimestampMillisecondType>();
1820
        test_layout::<TimestampMicrosecondType>();
1821
        test_layout::<TimestampNanosecondType>();
1822
        test_layout::<TimestampSecondType>();
1823
        test_layout::<Date32Type>();
1824
        test_layout::<Date64Type>();
1825
        test_layout::<Time32SecondType>();
1826
        test_layout::<Time32MillisecondType>();
1827
        test_layout::<Time64MicrosecondType>();
1828
        test_layout::<Time64NanosecondType>();
1829
        test_layout::<IntervalMonthDayNanoType>();
1830
        test_layout::<IntervalDayTimeType>();
1831
        test_layout::<IntervalYearMonthType>();
1832
        test_layout::<DurationNanosecondType>();
1833
        test_layout::<DurationMicrosecondType>();
1834
        test_layout::<DurationMillisecondType>();
1835
        test_layout::<DurationSecondType>();
1836
    }
1837
}