## 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
    }