Coverage Report

Created: 2025-08-26 07:03

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::{i256, Buffer, OffsetBuffer};
27
use arrow_data::decimal::{
28
    is_validate_decimal256_precision, is_validate_decimal32_precision,
29
    is_validate_decimal64_precision, is_validate_decimal_precision, validate_decimal256_precision,
30
    validate_decimal32_precision, validate_decimal64_precision, validate_decimal_precision,
31
};
32
use arrow_data::{validate_binary_view, validate_string_view};
33
use arrow_schema::{
34
    ArrowError, DataType, IntervalUnit, TimeUnit, DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE,
35
    DECIMAL256_MAX_PRECISION, DECIMAL256_MAX_SCALE, DECIMAL32_DEFAULT_SCALE,
36
    DECIMAL32_MAX_PRECISION, DECIMAL32_MAX_SCALE, DECIMAL64_DEFAULT_SCALE, DECIMAL64_MAX_PRECISION,
37
    DECIMAL64_MAX_SCALE, DECIMAL_DEFAULT_SCALE,
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
0
    fn default_value() -> Self::Native {
78
0
        Default::default()
79
0
    }
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
0
    pub fn make_value(
831
0
        years: i32,
832
0
        months: i32,
833
0
    ) -> <IntervalYearMonthType as ArrowPrimitiveType>::Native {
834
0
        years * 12 + months
835
0
    }
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
0
    pub fn make_value(days: i32, milliseconds: i32) -> IntervalDayTime {
859
0
        IntervalDayTime { days, milliseconds }
860
0
    }
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
4
    pub fn make_value(months: i32, days: i32, nanoseconds: i64) -> IntervalMonthDayNano {
883
4
        IntervalMonthDayNano {
884
4
            months,
885
4
            days,
886
4
            nanoseconds,
887
4
        }
888
4
    }
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
    /// fn to create its [`DataType`]
1327
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType;
1328
    /// Default values for [`DataType`]
1329
    const DEFAULT_TYPE: DataType;
1330
1331
    /// "Decimal32", "Decimal64", "Decimal128" or "Decimal256", for use in error messages
1332
    const PREFIX: &'static str;
1333
1334
    /// Formats the decimal value with the provided precision and scale
1335
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String;
1336
1337
    /// Validates that `value` contains no more than `precision` decimal digits
1338
    fn validate_decimal_precision(value: Self::Native, precision: u8) -> Result<(), ArrowError>;
1339
1340
    /// Determines whether `value` contains no more than `precision` decimal digits
1341
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool;
1342
}
1343
1344
/// Validate that `precision` and `scale` are valid for `T`
1345
///
1346
/// Returns an Error if:
1347
/// - `precision` is zero
1348
/// - `precision` is larger than `T:MAX_PRECISION`
1349
/// - `scale` is larger than `T::MAX_SCALE`
1350
/// - `scale` is > `precision`
1351
64
pub fn validate_decimal_precision_and_scale<T: DecimalType>(
1352
64
    precision: u8,
1353
64
    scale: i8,
1354
64
) -> Result<(), ArrowError> {
1355
64
    if precision == 0 {
1356
0
        return Err(ArrowError::InvalidArgumentError(format!(
1357
0
            "precision cannot be 0, has to be between [1, {}]",
1358
0
            T::MAX_PRECISION
1359
0
        )));
1360
64
    }
1361
64
    if precision > T::MAX_PRECISION {
1362
0
        return Err(ArrowError::InvalidArgumentError(format!(
1363
0
            "precision {} is greater than max {}",
1364
0
            precision,
1365
0
            T::MAX_PRECISION
1366
0
        )));
1367
64
    }
1368
64
    if scale > T::MAX_SCALE {
1369
0
        return Err(ArrowError::InvalidArgumentError(format!(
1370
0
            "scale {} is greater than max {}",
1371
0
            scale,
1372
0
            T::MAX_SCALE
1373
0
        )));
1374
64
    }
1375
64
    if scale > 0 && scale as u8 > precision {
1376
0
        return Err(ArrowError::InvalidArgumentError(format!(
1377
0
            "scale {scale} is greater than precision {precision}"
1378
0
        )));
1379
64
    }
1380
1381
64
    Ok(())
1382
64
}
1383
1384
/// The decimal type for a Decimal32Array
1385
#[derive(Debug)]
1386
pub struct Decimal32Type {}
1387
1388
impl DecimalType for Decimal32Type {
1389
    const BYTE_LENGTH: usize = 4;
1390
    const MAX_PRECISION: u8 = DECIMAL32_MAX_PRECISION;
1391
    const MAX_SCALE: i8 = DECIMAL32_MAX_SCALE;
1392
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal32;
1393
    const DEFAULT_TYPE: DataType =
1394
        DataType::Decimal32(DECIMAL32_MAX_PRECISION, DECIMAL32_DEFAULT_SCALE);
1395
    const PREFIX: &'static str = "Decimal32";
1396
1397
0
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1398
0
        format_decimal_str(&value.to_string(), precision as usize, scale)
1399
0
    }
1400
1401
0
    fn validate_decimal_precision(num: i32, precision: u8) -> Result<(), ArrowError> {
1402
0
        validate_decimal32_precision(num, precision)
1403
0
    }
1404
1405
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1406
0
        is_validate_decimal32_precision(value, precision)
1407
0
    }
1408
}
1409
1410
impl ArrowPrimitiveType for Decimal32Type {
1411
    type Native = i32;
1412
1413
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1414
}
1415
1416
impl primitive::PrimitiveTypeSealed for Decimal32Type {}
1417
1418
/// The decimal type for a Decimal64Array
1419
#[derive(Debug)]
1420
pub struct Decimal64Type {}
1421
1422
impl DecimalType for Decimal64Type {
1423
    const BYTE_LENGTH: usize = 8;
1424
    const MAX_PRECISION: u8 = DECIMAL64_MAX_PRECISION;
1425
    const MAX_SCALE: i8 = DECIMAL64_MAX_SCALE;
1426
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal64;
1427
    const DEFAULT_TYPE: DataType =
1428
        DataType::Decimal64(DECIMAL64_MAX_PRECISION, DECIMAL64_DEFAULT_SCALE);
1429
    const PREFIX: &'static str = "Decimal64";
1430
1431
0
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1432
0
        format_decimal_str(&value.to_string(), precision as usize, scale)
1433
0
    }
1434
1435
0
    fn validate_decimal_precision(num: i64, precision: u8) -> Result<(), ArrowError> {
1436
0
        validate_decimal64_precision(num, precision)
1437
0
    }
1438
1439
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1440
0
        is_validate_decimal64_precision(value, precision)
1441
0
    }
1442
}
1443
1444
impl ArrowPrimitiveType for Decimal64Type {
1445
    type Native = i64;
1446
1447
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1448
}
1449
1450
impl primitive::PrimitiveTypeSealed for Decimal64Type {}
1451
1452
/// The decimal type for a Decimal128Array
1453
#[derive(Debug)]
1454
pub struct Decimal128Type {}
1455
1456
impl DecimalType for Decimal128Type {
1457
    const BYTE_LENGTH: usize = 16;
1458
    const MAX_PRECISION: u8 = DECIMAL128_MAX_PRECISION;
1459
    const MAX_SCALE: i8 = DECIMAL128_MAX_SCALE;
1460
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal128;
1461
    const DEFAULT_TYPE: DataType =
1462
        DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1463
    const PREFIX: &'static str = "Decimal128";
1464
1465
6
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1466
6
        format_decimal_str(&value.to_string(), precision as usize, scale)
1467
6
    }
1468
1469
0
    fn validate_decimal_precision(num: i128, precision: u8) -> Result<(), ArrowError> {
1470
0
        validate_decimal_precision(num, precision)
1471
0
    }
1472
1473
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1474
0
        is_validate_decimal_precision(value, precision)
1475
0
    }
1476
}
1477
1478
impl ArrowPrimitiveType for Decimal128Type {
1479
    type Native = i128;
1480
1481
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1482
}
1483
1484
impl primitive::PrimitiveTypeSealed for Decimal128Type {}
1485
1486
/// The decimal type for a Decimal256Array
1487
#[derive(Debug)]
1488
pub struct Decimal256Type {}
1489
1490
impl DecimalType for Decimal256Type {
1491
    const BYTE_LENGTH: usize = 32;
1492
    const MAX_PRECISION: u8 = DECIMAL256_MAX_PRECISION;
1493
    const MAX_SCALE: i8 = DECIMAL256_MAX_SCALE;
1494
    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal256;
1495
    const DEFAULT_TYPE: DataType =
1496
        DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1497
    const PREFIX: &'static str = "Decimal256";
1498
1499
2
    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1500
2
        format_decimal_str(&value.to_string(), precision as usize, scale)
1501
2
    }
1502
1503
0
    fn validate_decimal_precision(num: i256, precision: u8) -> Result<(), ArrowError> {
1504
0
        validate_decimal256_precision(num, precision)
1505
0
    }
1506
1507
0
    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1508
0
        is_validate_decimal256_precision(value, precision)
1509
0
    }
1510
}
1511
1512
impl ArrowPrimitiveType for Decimal256Type {
1513
    type Native = i256;
1514
1515
    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1516
}
1517
1518
impl primitive::PrimitiveTypeSealed for Decimal256Type {}
1519
1520
8
fn format_decimal_str(value_str: &str, precision: usize, scale: i8) -> String {
1521
8
    let (sign, rest) = match value_str.strip_prefix('-') {
1522
4
        Some(stripped) => ("-", stripped),
1523
4
        None => ("", value_str),
1524
    };
1525
8
    let bound = precision.min(rest.len()) + sign.len();
1526
8
    let value_str = &value_str[0..bound];
1527
1528
8
    if scale == 0 {
1529
0
        value_str.to_string()
1530
8
    } else if scale < 0 {
1531
0
        let padding = value_str.len() + scale.unsigned_abs() as usize;
1532
0
        format!("{value_str:0<padding$}")
1533
8
    } else if rest.len() > scale as usize {
1534
        // Decimal separator is in the middle of the string
1535
8
        let (whole, decimal) = value_str.split_at(value_str.len() - scale as usize);
1536
8
        format!("{whole}.{decimal}")
1537
    } else {
1538
        // String has to be padded
1539
0
        format!("{}0.{:0>width$}", sign, rest, width = scale as usize)
1540
    }
1541
8
}
1542
1543
/// Crate private types for Byte Arrays
1544
///
1545
/// Not intended to be used outside this crate
1546
pub(crate) mod bytes {
1547
    use super::*;
1548
1549
    pub trait ByteArrayTypeSealed {}
1550
    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericStringType<O> {}
1551
    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericBinaryType<O> {}
1552
1553
    pub trait ByteArrayNativeType: std::fmt::Debug + Send + Sync {
1554
        fn from_bytes_checked(b: &[u8]) -> Option<&Self>;
1555
1556
        /// # Safety
1557
        ///
1558
        /// `b` must be a valid byte sequence for `Self`
1559
        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self;
1560
    }
1561
1562
    impl ByteArrayNativeType for [u8] {
1563
        #[inline]
1564
        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1565
            Some(b)
1566
        }
1567
1568
        #[inline]
1569
94
        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1570
94
            b
1571
94
        }
1572
    }
1573
1574
    impl ByteArrayNativeType for str {
1575
        #[inline]
1576
        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1577
            std::str::from_utf8(b).ok()
1578
        }
1579
1580
        #[inline]
1581
40
        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1582
40
            std::str::from_utf8_unchecked(b)
1583
40
        }
1584
    }
1585
}
1586
1587
/// A trait over the variable-size byte array types
1588
///
1589
/// See [Variable Size Binary Layout](https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout)
1590
pub trait ByteArrayType: 'static + Send + Sync + bytes::ByteArrayTypeSealed {
1591
    /// Type of offset i.e i32/i64
1592
    type Offset: OffsetSizeTrait;
1593
    /// Type for representing its equivalent rust type i.e
1594
    /// Utf8Array will have native type has &str
1595
    /// BinaryArray will have type as [u8]
1596
    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1597
1598
    /// "Binary" or "String", for use in error messages
1599
    const PREFIX: &'static str;
1600
1601
    /// Datatype of array elements
1602
    const DATA_TYPE: DataType;
1603
1604
    /// Verifies that every consecutive pair of `offsets` denotes a valid slice of `values`
1605
    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError>;
1606
}
1607
1608
/// [`ByteArrayType`] for string arrays
1609
pub struct GenericStringType<O: OffsetSizeTrait> {
1610
    phantom: PhantomData<O>,
1611
}
1612
1613
impl<O: OffsetSizeTrait> ByteArrayType for GenericStringType<O> {
1614
    type Offset = O;
1615
    type Native = str;
1616
    const PREFIX: &'static str = "String";
1617
1618
    const DATA_TYPE: DataType = if O::IS_LARGE {
1619
        DataType::LargeUtf8
1620
    } else {
1621
        DataType::Utf8
1622
    };
1623
1624
65
    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1625
        // Verify that the slice as a whole is valid UTF-8
1626
65
        let validated = std::str::from_utf8(values).map_err(|e| 
{0
1627
0
            ArrowError::InvalidArgumentError(format!("Encountered non UTF-8 data: {e}"))
1628
0
        })?;
1629
1630
        // Verify each offset is at a valid character boundary in this UTF-8 array
1631
354
        for offset in 
offsets65
.
iter65
() {
1632
354
            let o = offset.as_usize();
1633
354
            if !validated.is_char_boundary(o) {
1634
0
                if o < validated.len() {
1635
0
                    return Err(ArrowError::InvalidArgumentError(format!(
1636
0
                        "Split UTF-8 codepoint at offset {o}"
1637
0
                    )));
1638
0
                }
1639
0
                return Err(ArrowError::InvalidArgumentError(format!(
1640
0
                    "Offset of {o} exceeds length of values {}",
1641
0
                    validated.len()
1642
0
                )));
1643
354
            }
1644
        }
1645
65
        Ok(())
1646
65
    }
1647
}
1648
1649
/// An arrow utf8 array with i32 offsets
1650
pub type Utf8Type = GenericStringType<i32>;
1651
/// An arrow utf8 array with i64 offsets
1652
pub type LargeUtf8Type = GenericStringType<i64>;
1653
1654
/// [`ByteArrayType`] for binary arrays
1655
pub struct GenericBinaryType<O: OffsetSizeTrait> {
1656
    phantom: PhantomData<O>,
1657
}
1658
1659
impl<O: OffsetSizeTrait> ByteArrayType for GenericBinaryType<O> {
1660
    type Offset = O;
1661
    type Native = [u8];
1662
    const PREFIX: &'static str = "Binary";
1663
1664
    const DATA_TYPE: DataType = if O::IS_LARGE {
1665
        DataType::LargeBinary
1666
    } else {
1667
        DataType::Binary
1668
    };
1669
1670
80
    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1671
        // offsets are guaranteed to be monotonically increasing and non-empty
1672
80
        let max_offset = offsets.last().unwrap().as_usize();
1673
80
        if values.len() < max_offset {
1674
0
            return Err(ArrowError::InvalidArgumentError(format!(
1675
0
                "Maximum offset of {max_offset} is larger than values of length {}",
1676
0
                values.len()
1677
0
            )));
1678
80
        }
1679
80
        Ok(())
1680
80
    }
1681
}
1682
1683
/// An arrow binary array with i32 offsets
1684
pub type BinaryType = GenericBinaryType<i32>;
1685
/// An arrow binary array with i64 offsets
1686
pub type LargeBinaryType = GenericBinaryType<i64>;
1687
1688
mod byte_view {
1689
    use crate::types::{BinaryViewType, StringViewType};
1690
1691
    pub trait Sealed: Send + Sync {}
1692
    impl Sealed for StringViewType {}
1693
    impl Sealed for BinaryViewType {}
1694
}
1695
1696
/// A trait over the variable length bytes view array types
1697
pub trait ByteViewType: byte_view::Sealed + 'static + PartialEq + Send + Sync {
1698
    /// If element in array is utf8 encoded string.
1699
    const IS_UTF8: bool;
1700
1701
    /// Datatype of array elements
1702
    const DATA_TYPE: DataType = if Self::IS_UTF8 {
1703
        DataType::Utf8View
1704
    } else {
1705
        DataType::BinaryView
1706
    };
1707
1708
    /// "Binary" or "String", for use in displayed or error messages
1709
    const PREFIX: &'static str;
1710
1711
    /// Type for representing its equivalent rust type i.e
1712
    /// Utf8Array will have native type has &str
1713
    /// BinaryArray will have type as [u8]
1714
    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1715
1716
    /// Type for owned corresponding to `Native`
1717
    type Owned: Debug + Clone + Sync + Send + AsRef<Self::Native>;
1718
1719
    /// Verifies that the provided buffers are valid for this array type
1720
    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError>;
1721
}
1722
1723
/// [`ByteViewType`] for string arrays
1724
#[derive(PartialEq)]
1725
pub struct StringViewType {}
1726
1727
impl ByteViewType for StringViewType {
1728
    const IS_UTF8: bool = true;
1729
    const PREFIX: &'static str = "String";
1730
1731
    type Native = str;
1732
    type Owned = String;
1733
1734
0
    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1735
0
        validate_string_view(views, buffers)
1736
0
    }
1737
}
1738
1739
/// [`BinaryViewType`] for string arrays
1740
#[derive(PartialEq)]
1741
pub struct BinaryViewType {}
1742
1743
impl ByteViewType for BinaryViewType {
1744
    const IS_UTF8: bool = false;
1745
    const PREFIX: &'static str = "Binary";
1746
    type Native = [u8];
1747
    type Owned = Vec<u8>;
1748
1749
0
    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1750
0
        validate_binary_view(views, buffers)
1751
0
    }
1752
}
1753
1754
#[cfg(test)]
1755
mod tests {
1756
    use super::*;
1757
    use arrow_data::{layout, BufferSpec};
1758
1759
    #[test]
1760
    fn month_day_nano_should_roundtrip() {
1761
        let value = IntervalMonthDayNanoType::make_value(1, 2, 3);
1762
        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (1, 2, 3));
1763
    }
1764
1765
    #[test]
1766
    fn month_day_nano_should_roundtrip_neg() {
1767
        let value = IntervalMonthDayNanoType::make_value(-1, -2, -3);
1768
        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (-1, -2, -3));
1769
    }
1770
1771
    #[test]
1772
    fn day_time_should_roundtrip() {
1773
        let value = IntervalDayTimeType::make_value(1, 2);
1774
        assert_eq!(IntervalDayTimeType::to_parts(value), (1, 2));
1775
    }
1776
1777
    #[test]
1778
    fn day_time_should_roundtrip_neg() {
1779
        let value = IntervalDayTimeType::make_value(-1, -2);
1780
        assert_eq!(IntervalDayTimeType::to_parts(value), (-1, -2));
1781
    }
1782
1783
    #[test]
1784
    fn year_month_should_roundtrip() {
1785
        let value = IntervalYearMonthType::make_value(1, 2);
1786
        assert_eq!(IntervalYearMonthType::to_months(value), 14);
1787
    }
1788
1789
    #[test]
1790
    fn year_month_should_roundtrip_neg() {
1791
        let value = IntervalYearMonthType::make_value(-1, -2);
1792
        assert_eq!(IntervalYearMonthType::to_months(value), -14);
1793
    }
1794
1795
    fn test_layout<T: ArrowPrimitiveType>() {
1796
        let layout = layout(&T::DATA_TYPE);
1797
1798
        assert_eq!(layout.buffers.len(), 1);
1799
1800
        let spec = &layout.buffers[0];
1801
        assert_eq!(
1802
            spec,
1803
            &BufferSpec::FixedWidth {
1804
                byte_width: std::mem::size_of::<T::Native>(),
1805
                alignment: std::mem::align_of::<T::Native>(),
1806
            }
1807
        );
1808
    }
1809
1810
    #[test]
1811
    fn test_layouts() {
1812
        test_layout::<Int8Type>();
1813
        test_layout::<Int16Type>();
1814
        test_layout::<Int32Type>();
1815
        test_layout::<Int64Type>();
1816
        test_layout::<UInt8Type>();
1817
        test_layout::<UInt16Type>();
1818
        test_layout::<UInt32Type>();
1819
        test_layout::<UInt64Type>();
1820
        test_layout::<Float16Type>();
1821
        test_layout::<Float32Type>();
1822
        test_layout::<Float64Type>();
1823
        test_layout::<Decimal32Type>();
1824
        test_layout::<Decimal64Type>();
1825
        test_layout::<Decimal128Type>();
1826
        test_layout::<Decimal256Type>();
1827
        test_layout::<TimestampNanosecondType>();
1828
        test_layout::<TimestampMillisecondType>();
1829
        test_layout::<TimestampMicrosecondType>();
1830
        test_layout::<TimestampNanosecondType>();
1831
        test_layout::<TimestampSecondType>();
1832
        test_layout::<Date32Type>();
1833
        test_layout::<Date64Type>();
1834
        test_layout::<Time32SecondType>();
1835
        test_layout::<Time32MillisecondType>();
1836
        test_layout::<Time64MicrosecondType>();
1837
        test_layout::<Time64NanosecondType>();
1838
        test_layout::<IntervalMonthDayNanoType>();
1839
        test_layout::<IntervalDayTimeType>();
1840
        test_layout::<IntervalYearMonthType>();
1841
        test_layout::<DurationNanosecondType>();
1842
        test_layout::<DurationMicrosecondType>();
1843
        test_layout::<DurationMillisecondType>();
1844
        test_layout::<DurationSecondType>();
1845
    }
1846
}