arrow_array/
types.rs

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
20use crate::delta::{
21    add_days_datetime, add_months_datetime, shift_months, sub_days_datetime, sub_months_datetime,
22};
23use crate::temporal_conversions::as_datetime_with_timezone;
24use crate::timezone::Tz;
25use crate::{ArrowNativeTypeOp, OffsetSizeTrait};
26use arrow_buffer::{i256, Buffer, OffsetBuffer};
27use arrow_data::decimal::{
28    format_decimal_str, 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};
32use arrow_data::{validate_binary_view, validate_string_view};
33use 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};
39use chrono::{Duration, NaiveDate, NaiveDateTime};
40use half::f16;
41use std::fmt::Debug;
42use std::marker::PhantomData;
43use std::ops::{Add, Sub};
44
45// re-export types so that they can be used without importing arrow_buffer explicitly
46pub 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)]
52pub struct BooleanType {}
53
54impl 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
67pub 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    fn default_value() -> Self::Native {
78        Default::default()
79    }
80}
81
82mod primitive {
83    pub trait PrimitiveTypeSealed {}
84}
85
86macro_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
101make_type!(Int8Type, i8, DataType::Int8, "A signed 8-bit integer type.");
102make_type!(
103    Int16Type,
104    i16,
105    DataType::Int16,
106    "Signed 16-bit integer type."
107);
108make_type!(
109    Int32Type,
110    i32,
111    DataType::Int32,
112    "Signed 32-bit integer type."
113);
114make_type!(
115    Int64Type,
116    i64,
117    DataType::Int64,
118    "Signed 64-bit integer type."
119);
120make_type!(
121    UInt8Type,
122    u8,
123    DataType::UInt8,
124    "Unsigned 8-bit integer type."
125);
126make_type!(
127    UInt16Type,
128    u16,
129    DataType::UInt16,
130    "Unsigned 16-bit integer type."
131);
132make_type!(
133    UInt32Type,
134    u32,
135    DataType::UInt32,
136    "Unsigned 32-bit integer type."
137);
138make_type!(
139    UInt64Type,
140    u64,
141    DataType::UInt64,
142    "Unsigned 64-bit integer type."
143);
144make_type!(
145    Float16Type,
146    f16,
147    DataType::Float16,
148    "16-bit floating point number type."
149);
150make_type!(
151    Float32Type,
152    f32,
153    DataType::Float32,
154    "32-bit floating point number type."
155);
156make_type!(
157    Float64Type,
158    f64,
159    DataType::Float64,
160    "64-bit floating point number type."
161);
162make_type!(
163    TimestampSecondType,
164    i64,
165    DataType::Timestamp(TimeUnit::Second, None),
166    "Timestamp second type with an optional timezone."
167);
168make_type!(
169    TimestampMillisecondType,
170    i64,
171    DataType::Timestamp(TimeUnit::Millisecond, None),
172    "Timestamp millisecond type with an optional timezone."
173);
174make_type!(
175    TimestampMicrosecondType,
176    i64,
177    DataType::Timestamp(TimeUnit::Microsecond, None),
178    "Timestamp microsecond type with an optional timezone."
179);
180make_type!(
181    TimestampNanosecondType,
182    i64,
183    DataType::Timestamp(TimeUnit::Nanosecond, None),
184    "Timestamp nanosecond type with an optional timezone."
185);
186make_type!(
187    Date32Type,
188    i32,
189    DataType::Date32,
190    "32-bit date type: the elapsed time since UNIX epoch in days (32 bits)."
191);
192make_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);
200make_type!(
201    Time32SecondType,
202    i32,
203    DataType::Time32(TimeUnit::Second),
204    "32-bit time type: the elapsed time since midnight in seconds."
205);
206make_type!(
207    Time32MillisecondType,
208    i32,
209    DataType::Time32(TimeUnit::Millisecond),
210    "32-bit time type: the elapsed time since midnight in milliseconds."
211);
212make_type!(
213    Time64MicrosecondType,
214    i64,
215    DataType::Time64(TimeUnit::Microsecond),
216    "64-bit time type: the elapsed time since midnight in microseconds."
217);
218make_type!(
219    Time64NanosecondType,
220    i64,
221    DataType::Time64(TimeUnit::Nanosecond),
222    "64-bit time type: the elapsed time since midnight in nanoseconds."
223);
224make_type!(
225    IntervalYearMonthType,
226    i32,
227    DataType::Interval(IntervalUnit::YearMonth),
228    "32-bit “calendar” interval type: the number of whole months."
229);
230make_type!(
231    IntervalDayTimeType,
232    IntervalDayTime,
233    DataType::Interval(IntervalUnit::DayTime),
234    "“Calendar” interval type: days and milliseconds. See [`IntervalDayTime`] for more details."
235);
236make_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);
242make_type!(
243    DurationSecondType,
244    i64,
245    DataType::Duration(TimeUnit::Second),
246    "Elapsed time type: seconds."
247);
248make_type!(
249    DurationMillisecondType,
250    i64,
251    DataType::Duration(TimeUnit::Millisecond),
252    "Elapsed time type: milliseconds."
253);
254make_type!(
255    DurationMicrosecondType,
256    i64,
257    DataType::Duration(TimeUnit::Microsecond),
258    "Elapsed time type: microseconds."
259);
260make_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>
269pub trait ArrowDictionaryKeyType: ArrowPrimitiveType {}
270
271impl ArrowDictionaryKeyType for Int8Type {}
272
273impl ArrowDictionaryKeyType for Int16Type {}
274
275impl ArrowDictionaryKeyType for Int32Type {}
276
277impl ArrowDictionaryKeyType for Int64Type {}
278
279impl ArrowDictionaryKeyType for UInt8Type {}
280
281impl ArrowDictionaryKeyType for UInt16Type {}
282
283impl ArrowDictionaryKeyType for UInt32Type {}
284
285impl 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>
290pub trait RunEndIndexType: ArrowPrimitiveType {}
291
292impl RunEndIndexType for Int16Type {}
293
294impl RunEndIndexType for Int32Type {}
295
296impl RunEndIndexType for Int64Type {}
297
298/// A subtype of primitive type that represents temporal values.
299pub trait ArrowTemporalType: ArrowPrimitiveType {}
300
301impl ArrowTemporalType for TimestampSecondType {}
302impl ArrowTemporalType for TimestampMillisecondType {}
303impl ArrowTemporalType for TimestampMicrosecondType {}
304impl ArrowTemporalType for TimestampNanosecondType {}
305impl ArrowTemporalType for Date32Type {}
306impl ArrowTemporalType for Date64Type {}
307impl ArrowTemporalType for Time32SecondType {}
308impl ArrowTemporalType for Time32MillisecondType {}
309impl ArrowTemporalType for Time64MicrosecondType {}
310impl ArrowTemporalType for Time64NanosecondType {}
311// impl ArrowTemporalType for IntervalYearMonthType {}
312// impl ArrowTemporalType for IntervalDayTimeType {}
313// impl ArrowTemporalType for IntervalMonthDayNanoType {}
314impl ArrowTemporalType for DurationSecondType {}
315impl ArrowTemporalType for DurationMillisecondType {}
316impl ArrowTemporalType for DurationMicrosecondType {}
317impl ArrowTemporalType for DurationNanosecondType {}
318
319/// A timestamp type allows us to create array builders that take a timestamp.
320pub 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
330impl ArrowTimestampType for TimestampSecondType {
331    const UNIT: TimeUnit = TimeUnit::Second;
332
333    fn make_value(naive: NaiveDateTime) -> Option<i64> {
334        Some(naive.and_utc().timestamp())
335    }
336}
337impl ArrowTimestampType for TimestampMillisecondType {
338    const UNIT: TimeUnit = TimeUnit::Millisecond;
339
340    fn make_value(naive: NaiveDateTime) -> Option<i64> {
341        let utc = naive.and_utc();
342        let millis = utc.timestamp().checked_mul(1_000)?;
343        millis.checked_add(utc.timestamp_subsec_millis() as i64)
344    }
345}
346impl ArrowTimestampType for TimestampMicrosecondType {
347    const UNIT: TimeUnit = TimeUnit::Microsecond;
348
349    fn make_value(naive: NaiveDateTime) -> Option<i64> {
350        let utc = naive.and_utc();
351        let micros = utc.timestamp().checked_mul(1_000_000)?;
352        micros.checked_add(utc.timestamp_subsec_micros() as i64)
353    }
354}
355impl ArrowTimestampType for TimestampNanosecondType {
356    const UNIT: TimeUnit = TimeUnit::Nanosecond;
357
358    fn make_value(naive: NaiveDateTime) -> Option<i64> {
359        let utc = naive.and_utc();
360        let nanos = utc.timestamp().checked_mul(1_000_000_000)?;
361        nanos.checked_add(utc.timestamp_subsec_nanos() as i64)
362    }
363}
364
365fn add_year_months<T: ArrowTimestampType>(
366    timestamp: <T as ArrowPrimitiveType>::Native,
367    delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
368    tz: Tz,
369) -> Option<<T as ArrowPrimitiveType>::Native> {
370    let months = IntervalYearMonthType::to_months(delta);
371    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
372    let res = add_months_datetime(res, months)?;
373    let res = res.naive_utc();
374    T::make_value(res)
375}
376
377fn add_day_time<T: ArrowTimestampType>(
378    timestamp: <T as ArrowPrimitiveType>::Native,
379    delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
380    tz: Tz,
381) -> Option<<T as ArrowPrimitiveType>::Native> {
382    let (days, ms) = IntervalDayTimeType::to_parts(delta);
383    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
384    let res = add_days_datetime(res, days)?;
385    let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?;
386    let res = res.naive_utc();
387    T::make_value(res)
388}
389
390fn add_month_day_nano<T: ArrowTimestampType>(
391    timestamp: <T as ArrowPrimitiveType>::Native,
392    delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
393    tz: Tz,
394) -> Option<<T as ArrowPrimitiveType>::Native> {
395    let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
396    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
397    let res = add_months_datetime(res, months)?;
398    let res = add_days_datetime(res, days)?;
399    let res = res.checked_add_signed(Duration::nanoseconds(nanos))?;
400    let res = res.naive_utc();
401    T::make_value(res)
402}
403
404fn subtract_year_months<T: ArrowTimestampType>(
405    timestamp: <T as ArrowPrimitiveType>::Native,
406    delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
407    tz: Tz,
408) -> Option<<T as ArrowPrimitiveType>::Native> {
409    let months = IntervalYearMonthType::to_months(delta);
410    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
411    let res = sub_months_datetime(res, months)?;
412    let res = res.naive_utc();
413    T::make_value(res)
414}
415
416fn subtract_day_time<T: ArrowTimestampType>(
417    timestamp: <T as ArrowPrimitiveType>::Native,
418    delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
419    tz: Tz,
420) -> Option<<T as ArrowPrimitiveType>::Native> {
421    let (days, ms) = IntervalDayTimeType::to_parts(delta);
422    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
423    let res = sub_days_datetime(res, days)?;
424    let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?;
425    let res = res.naive_utc();
426    T::make_value(res)
427}
428
429fn subtract_month_day_nano<T: ArrowTimestampType>(
430    timestamp: <T as ArrowPrimitiveType>::Native,
431    delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
432    tz: Tz,
433) -> Option<<T as ArrowPrimitiveType>::Native> {
434    let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
435    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
436    let res = sub_months_datetime(res, months)?;
437    let res = sub_days_datetime(res, days)?;
438    let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?;
439    let res = res.naive_utc();
440    T::make_value(res)
441}
442
443impl 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    pub fn add_year_months(
454        timestamp: <Self as ArrowPrimitiveType>::Native,
455        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
456        tz: Tz,
457    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
458        add_year_months::<Self>(timestamp, delta, tz)
459    }
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    pub fn add_day_time(
471        timestamp: <Self as ArrowPrimitiveType>::Native,
472        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
473        tz: Tz,
474    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
475        add_day_time::<Self>(timestamp, delta, tz)
476    }
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    pub fn add_month_day_nano(
487        timestamp: <Self as ArrowPrimitiveType>::Native,
488        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
489        tz: Tz,
490    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
491        add_month_day_nano::<Self>(timestamp, delta, tz)
492    }
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    pub fn subtract_year_months(
504        timestamp: <Self as ArrowPrimitiveType>::Native,
505        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
506        tz: Tz,
507    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
508        subtract_year_months::<Self>(timestamp, delta, tz)
509    }
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    pub fn subtract_day_time(
521        timestamp: <Self as ArrowPrimitiveType>::Native,
522        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
523        tz: Tz,
524    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
525        subtract_day_time::<Self>(timestamp, delta, tz)
526    }
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    pub fn subtract_month_day_nano(
538        timestamp: <Self as ArrowPrimitiveType>::Native,
539        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
540        tz: Tz,
541    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
542        subtract_month_day_nano::<Self>(timestamp, delta, tz)
543    }
544}
545
546impl 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    pub fn add_year_months(
555        timestamp: <Self as ArrowPrimitiveType>::Native,
556        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
557        tz: Tz,
558    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
559        add_year_months::<Self>(timestamp, delta, tz)
560    }
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    pub fn add_day_time(
570        timestamp: <Self as ArrowPrimitiveType>::Native,
571        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
572        tz: Tz,
573    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
574        add_day_time::<Self>(timestamp, delta, tz)
575    }
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    pub fn add_month_day_nano(
585        timestamp: <Self as ArrowPrimitiveType>::Native,
586        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
587        tz: Tz,
588    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
589        add_month_day_nano::<Self>(timestamp, delta, tz)
590    }
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    pub fn subtract_year_months(
600        timestamp: <Self as ArrowPrimitiveType>::Native,
601        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
602        tz: Tz,
603    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
604        subtract_year_months::<Self>(timestamp, delta, tz)
605    }
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    pub fn subtract_day_time(
615        timestamp: <Self as ArrowPrimitiveType>::Native,
616        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
617        tz: Tz,
618    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
619        subtract_day_time::<Self>(timestamp, delta, tz)
620    }
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    pub fn subtract_month_day_nano(
630        timestamp: <Self as ArrowPrimitiveType>::Native,
631        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
632        tz: Tz,
633    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
634        subtract_month_day_nano::<Self>(timestamp, delta, tz)
635    }
636}
637
638impl 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    pub fn add_year_months(
647        timestamp: <Self as ArrowPrimitiveType>::Native,
648        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
649        tz: Tz,
650    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
651        add_year_months::<Self>(timestamp, delta, tz)
652    }
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    pub fn add_day_time(
662        timestamp: <Self as ArrowPrimitiveType>::Native,
663        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
664        tz: Tz,
665    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
666        add_day_time::<Self>(timestamp, delta, tz)
667    }
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    pub fn add_month_day_nano(
677        timestamp: <Self as ArrowPrimitiveType>::Native,
678        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
679        tz: Tz,
680    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
681        add_month_day_nano::<Self>(timestamp, delta, tz)
682    }
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    pub fn subtract_year_months(
692        timestamp: <Self as ArrowPrimitiveType>::Native,
693        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
694        tz: Tz,
695    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
696        subtract_year_months::<Self>(timestamp, delta, tz)
697    }
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    pub fn subtract_day_time(
707        timestamp: <Self as ArrowPrimitiveType>::Native,
708        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
709        tz: Tz,
710    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
711        subtract_day_time::<Self>(timestamp, delta, tz)
712    }
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    pub fn subtract_month_day_nano(
722        timestamp: <Self as ArrowPrimitiveType>::Native,
723        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
724        tz: Tz,
725    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
726        subtract_month_day_nano::<Self>(timestamp, delta, tz)
727    }
728}
729
730impl 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    pub fn add_year_months(
739        timestamp: <Self as ArrowPrimitiveType>::Native,
740        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
741        tz: Tz,
742    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
743        add_year_months::<Self>(timestamp, delta, tz)
744    }
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    pub fn add_day_time(
754        timestamp: <Self as ArrowPrimitiveType>::Native,
755        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
756        tz: Tz,
757    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
758        add_day_time::<Self>(timestamp, delta, tz)
759    }
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    pub fn add_month_day_nano(
769        timestamp: <Self as ArrowPrimitiveType>::Native,
770        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
771        tz: Tz,
772    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
773        add_month_day_nano::<Self>(timestamp, delta, tz)
774    }
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    pub fn subtract_year_months(
784        timestamp: <Self as ArrowPrimitiveType>::Native,
785        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
786        tz: Tz,
787    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
788        subtract_year_months::<Self>(timestamp, delta, tz)
789    }
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    pub fn subtract_day_time(
799        timestamp: <Self as ArrowPrimitiveType>::Native,
800        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
801        tz: Tz,
802    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
803        subtract_day_time::<Self>(timestamp, delta, tz)
804    }
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    pub fn subtract_month_day_nano(
814        timestamp: <Self as ArrowPrimitiveType>::Native,
815        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
816        tz: Tz,
817    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
818        subtract_month_day_nano::<Self>(timestamp, delta, tz)
819    }
820}
821
822impl IntervalYearMonthType {
823    /// Creates a IntervalYearMonthType::Native
824    ///
825    /// # Arguments
826    ///
827    /// * `years` - The number of years (+/-) represented in this interval
828    /// * `months` - The number of months (+/-) represented in this interval
829    #[inline]
830    pub fn make_value(
831        years: i32,
832        months: i32,
833    ) -> <IntervalYearMonthType as ArrowPrimitiveType>::Native {
834        years * 12 + months
835    }
836
837    /// Turns a IntervalYearMonthType type into an i32 of months.
838    ///
839    /// This operation is technically a no-op, it is included for comprehensiveness.
840    ///
841    /// # Arguments
842    ///
843    /// * `i` - The IntervalYearMonthType::Native to convert
844    #[inline]
845    pub fn to_months(i: <IntervalYearMonthType as ArrowPrimitiveType>::Native) -> i32 {
846        i
847    }
848}
849
850impl IntervalDayTimeType {
851    /// Creates a IntervalDayTimeType::Native
852    ///
853    /// # Arguments
854    ///
855    /// * `days` - The number of days (+/-) represented in this interval
856    /// * `millis` - The number of milliseconds (+/-) represented in this interval
857    #[inline]
858    pub fn make_value(days: i32, milliseconds: i32) -> IntervalDayTime {
859        IntervalDayTime { days, milliseconds }
860    }
861
862    /// Turns a IntervalDayTimeType into a tuple of (days, milliseconds)
863    ///
864    /// # Arguments
865    ///
866    /// * `i` - The IntervalDayTimeType to convert
867    #[inline]
868    pub fn to_parts(i: IntervalDayTime) -> (i32, i32) {
869        (i.days, i.milliseconds)
870    }
871}
872
873impl IntervalMonthDayNanoType {
874    /// Creates a IntervalMonthDayNanoType::Native
875    ///
876    /// # Arguments
877    ///
878    /// * `months` - The number of months (+/-) represented in this interval
879    /// * `days` - The number of days (+/-) represented in this interval
880    /// * `nanos` - The number of nanoseconds (+/-) represented in this interval
881    #[inline]
882    pub fn make_value(months: i32, days: i32, nanoseconds: i64) -> IntervalMonthDayNano {
883        IntervalMonthDayNano {
884            months,
885            days,
886            nanoseconds,
887        }
888    }
889
890    /// Turns a IntervalMonthDayNanoType into a tuple of (months, days, nanos)
891    ///
892    /// # Arguments
893    ///
894    /// * `i` - The IntervalMonthDayNanoType to convert
895    #[inline]
896    pub fn to_parts(i: IntervalMonthDayNano) -> (i32, i32, i64) {
897        (i.months, i.days, i.nanoseconds)
898    }
899}
900
901impl Date32Type {
902    /// Converts an arrow Date32Type into a chrono::NaiveDate
903    ///
904    /// # Arguments
905    ///
906    /// * `i` - The Date32Type to convert
907    pub fn to_naive_date(i: <Date32Type as ArrowPrimitiveType>::Native) -> NaiveDate {
908        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
909        epoch.add(Duration::try_days(i as i64).unwrap())
910    }
911
912    /// Converts a chrono::NaiveDate into an arrow Date32Type
913    ///
914    /// # Arguments
915    ///
916    /// * `d` - The NaiveDate to convert
917    pub fn from_naive_date(d: NaiveDate) -> <Date32Type as ArrowPrimitiveType>::Native {
918        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
919        d.sub(epoch).num_days() as <Date32Type as ArrowPrimitiveType>::Native
920    }
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    pub fn add_year_months(
929        date: <Date32Type as ArrowPrimitiveType>::Native,
930        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
931    ) -> <Date32Type as ArrowPrimitiveType>::Native {
932        let prior = Date32Type::to_naive_date(date);
933        let months = IntervalYearMonthType::to_months(delta);
934        let posterior = shift_months(prior, months);
935        Date32Type::from_naive_date(posterior)
936    }
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    pub fn add_day_time(
945        date: <Date32Type as ArrowPrimitiveType>::Native,
946        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
947    ) -> <Date32Type as ArrowPrimitiveType>::Native {
948        let (days, ms) = IntervalDayTimeType::to_parts(delta);
949        let res = Date32Type::to_naive_date(date);
950        let res = res.add(Duration::try_days(days as i64).unwrap());
951        let res = res.add(Duration::try_milliseconds(ms as i64).unwrap());
952        Date32Type::from_naive_date(res)
953    }
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    pub fn add_month_day_nano(
962        date: <Date32Type as ArrowPrimitiveType>::Native,
963        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
964    ) -> <Date32Type as ArrowPrimitiveType>::Native {
965        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
966        let res = Date32Type::to_naive_date(date);
967        let res = shift_months(res, months);
968        let res = res.add(Duration::try_days(days as i64).unwrap());
969        let res = res.add(Duration::nanoseconds(nanos));
970        Date32Type::from_naive_date(res)
971    }
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    pub fn subtract_year_months(
980        date: <Date32Type as ArrowPrimitiveType>::Native,
981        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
982    ) -> <Date32Type as ArrowPrimitiveType>::Native {
983        let prior = Date32Type::to_naive_date(date);
984        let months = IntervalYearMonthType::to_months(-delta);
985        let posterior = shift_months(prior, months);
986        Date32Type::from_naive_date(posterior)
987    }
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    pub fn subtract_day_time(
996        date: <Date32Type as ArrowPrimitiveType>::Native,
997        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
998    ) -> <Date32Type as ArrowPrimitiveType>::Native {
999        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1000        let res = Date32Type::to_naive_date(date);
1001        let res = res.sub(Duration::try_days(days as i64).unwrap());
1002        let res = res.sub(Duration::try_milliseconds(ms as i64).unwrap());
1003        Date32Type::from_naive_date(res)
1004    }
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    pub fn subtract_month_day_nano(
1013        date: <Date32Type as ArrowPrimitiveType>::Native,
1014        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1015    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1016        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1017        let res = Date32Type::to_naive_date(date);
1018        let res = shift_months(res, -months);
1019        let res = res.sub(Duration::try_days(days as i64).unwrap());
1020        let res = res.sub(Duration::nanoseconds(nanos));
1021        Date32Type::from_naive_date(res)
1022    }
1023}
1024
1025impl 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    pub fn to_naive_date(i: <Date64Type as ArrowPrimitiveType>::Native) -> NaiveDate {
1033        Self::to_naive_date_opt(i)
1034            .unwrap_or_else(|| panic!("Date64Type::to_naive_date overflowed for date: {i}",))
1035    }
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    pub fn to_naive_date_opt(i: <Date64Type as ArrowPrimitiveType>::Native) -> Option<NaiveDate> {
1048        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1049        Duration::try_milliseconds(i).and_then(|d| epoch.checked_add_signed(d))
1050    }
1051
1052    /// Converts a chrono::NaiveDate into an arrow Date64Type
1053    ///
1054    /// # Arguments
1055    ///
1056    /// * `d` - The NaiveDate to convert
1057    pub fn from_naive_date(d: NaiveDate) -> <Date64Type as ArrowPrimitiveType>::Native {
1058        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1059        d.sub(epoch).num_milliseconds() as <Date64Type as ArrowPrimitiveType>::Native
1060    }
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    pub fn add_year_months(
1073        date: <Date64Type as ArrowPrimitiveType>::Native,
1074        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1075    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1076        Self::add_year_months_opt(date, delta).unwrap_or_else(|| {
1077            panic!("Date64Type::add_year_months overflowed for date: {date}, delta: {delta}",)
1078        })
1079    }
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    pub fn add_year_months_opt(
1090        date: <Date64Type as ArrowPrimitiveType>::Native,
1091        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1092    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1093        let prior = Date64Type::to_naive_date_opt(date)?;
1094        let months = IntervalYearMonthType::to_months(delta);
1095        let posterior = shift_months(prior, months);
1096        Some(Date64Type::from_naive_date(posterior))
1097    }
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    pub fn add_day_time(
1110        date: <Date64Type as ArrowPrimitiveType>::Native,
1111        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1112    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1113        Self::add_day_time_opt(date, delta).unwrap_or_else(|| {
1114            panic!("Date64Type::add_day_time overflowed for date: {date}, delta: {delta:?}",)
1115        })
1116    }
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    pub fn add_day_time_opt(
1127        date: <Date64Type as ArrowPrimitiveType>::Native,
1128        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1129    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1130        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1131        let res = Date64Type::to_naive_date_opt(date)?;
1132        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1133        let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?;
1134        Some(Date64Type::from_naive_date(res))
1135    }
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    pub fn add_month_day_nano(
1148        date: <Date64Type as ArrowPrimitiveType>::Native,
1149        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1150    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1151        Self::add_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1152            panic!("Date64Type::add_month_day_nano overflowed for date: {date}, delta: {delta:?}",)
1153        })
1154    }
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    pub fn add_month_day_nano_opt(
1165        date: <Date64Type as ArrowPrimitiveType>::Native,
1166        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1167    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1168        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1169        let res = Date64Type::to_naive_date_opt(date)?;
1170        let res = shift_months(res, months);
1171        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1172        let res = res.checked_add_signed(Duration::nanoseconds(nanos))?;
1173        Some(Date64Type::from_naive_date(res))
1174    }
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    pub fn subtract_year_months(
1187        date: <Date64Type as ArrowPrimitiveType>::Native,
1188        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1189    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1190        Self::subtract_year_months_opt(date, delta).unwrap_or_else(|| {
1191            panic!("Date64Type::subtract_year_months overflowed for date: {date}, delta: {delta}",)
1192        })
1193    }
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    pub fn subtract_year_months_opt(
1204        date: <Date64Type as ArrowPrimitiveType>::Native,
1205        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1206    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1207        let prior = Date64Type::to_naive_date_opt(date)?;
1208        let months = IntervalYearMonthType::to_months(-delta);
1209        let posterior = shift_months(prior, months);
1210        Some(Date64Type::from_naive_date(posterior))
1211    }
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    pub fn subtract_day_time(
1224        date: <Date64Type as ArrowPrimitiveType>::Native,
1225        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1226    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1227        Self::subtract_day_time_opt(date, delta).unwrap_or_else(|| {
1228            panic!("Date64Type::subtract_day_time overflowed for date: {date}, delta: {delta:?}",)
1229        })
1230    }
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    pub fn subtract_day_time_opt(
1241        date: <Date64Type as ArrowPrimitiveType>::Native,
1242        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1243    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1244        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1245        let res = Date64Type::to_naive_date_opt(date)?;
1246        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1247        let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?;
1248        Some(Date64Type::from_naive_date(res))
1249    }
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    pub fn subtract_month_day_nano(
1262        date: <Date64Type as ArrowPrimitiveType>::Native,
1263        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1264    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1265        Self::subtract_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1266            panic!(
1267                "Date64Type::subtract_month_day_nano overflowed for date: {date}, delta: {delta:?}",
1268            )
1269        })
1270    }
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    pub fn subtract_month_day_nano_opt(
1281        date: <Date64Type as ArrowPrimitiveType>::Native,
1282        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1283    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1284        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1285        let res = Date64Type::to_naive_date_opt(date)?;
1286        let res = shift_months(res, -months);
1287        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1288        let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?;
1289        Some(Date64Type::from_naive_date(res))
1290    }
1291}
1292
1293/// Crate private types for Decimal Arrays
1294///
1295/// Not intended to be used outside this crate
1296mod 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
1317pub 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(
1339        value: Self::Native,
1340        precision: u8,
1341        scale: i8,
1342    ) -> Result<(), ArrowError>;
1343
1344    /// Determines whether `value` contains no more than `precision` decimal digits
1345    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool;
1346}
1347
1348/// Validate that `precision` and `scale` are valid for `T`
1349///
1350/// Returns an Error if:
1351/// - `precision` is zero
1352/// - `precision` is larger than `T:MAX_PRECISION`
1353/// - `scale` is larger than `T::MAX_SCALE`
1354/// - `scale` is > `precision`
1355pub fn validate_decimal_precision_and_scale<T: DecimalType>(
1356    precision: u8,
1357    scale: i8,
1358) -> Result<(), ArrowError> {
1359    if precision == 0 {
1360        return Err(ArrowError::InvalidArgumentError(format!(
1361            "precision cannot be 0, has to be between [1, {}]",
1362            T::MAX_PRECISION
1363        )));
1364    }
1365    if precision > T::MAX_PRECISION {
1366        return Err(ArrowError::InvalidArgumentError(format!(
1367            "precision {} is greater than max {}",
1368            precision,
1369            T::MAX_PRECISION
1370        )));
1371    }
1372    if scale > T::MAX_SCALE {
1373        return Err(ArrowError::InvalidArgumentError(format!(
1374            "scale {} is greater than max {}",
1375            scale,
1376            T::MAX_SCALE
1377        )));
1378    }
1379    if scale > 0 && scale as u8 > precision {
1380        return Err(ArrowError::InvalidArgumentError(format!(
1381            "scale {scale} is greater than precision {precision}"
1382        )));
1383    }
1384
1385    Ok(())
1386}
1387
1388/// The decimal type for a Decimal32Array
1389#[derive(Debug)]
1390pub struct Decimal32Type {}
1391
1392impl DecimalType for Decimal32Type {
1393    const BYTE_LENGTH: usize = 4;
1394    const MAX_PRECISION: u8 = DECIMAL32_MAX_PRECISION;
1395    const MAX_SCALE: i8 = DECIMAL32_MAX_SCALE;
1396    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal32;
1397    const DEFAULT_TYPE: DataType =
1398        DataType::Decimal32(DECIMAL32_MAX_PRECISION, DECIMAL32_DEFAULT_SCALE);
1399    const PREFIX: &'static str = "Decimal32";
1400
1401    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1402        format_decimal_str(&value.to_string(), precision as usize, scale)
1403    }
1404
1405    fn validate_decimal_precision(num: i32, precision: u8, scale: i8) -> Result<(), ArrowError> {
1406        validate_decimal32_precision(num, precision, scale)
1407    }
1408
1409    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1410        is_validate_decimal32_precision(value, precision)
1411    }
1412}
1413
1414impl ArrowPrimitiveType for Decimal32Type {
1415    type Native = i32;
1416
1417    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1418}
1419
1420impl primitive::PrimitiveTypeSealed for Decimal32Type {}
1421
1422/// The decimal type for a Decimal64Array
1423#[derive(Debug)]
1424pub struct Decimal64Type {}
1425
1426impl DecimalType for Decimal64Type {
1427    const BYTE_LENGTH: usize = 8;
1428    const MAX_PRECISION: u8 = DECIMAL64_MAX_PRECISION;
1429    const MAX_SCALE: i8 = DECIMAL64_MAX_SCALE;
1430    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal64;
1431    const DEFAULT_TYPE: DataType =
1432        DataType::Decimal64(DECIMAL64_MAX_PRECISION, DECIMAL64_DEFAULT_SCALE);
1433    const PREFIX: &'static str = "Decimal64";
1434
1435    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1436        format_decimal_str(&value.to_string(), precision as usize, scale)
1437    }
1438
1439    fn validate_decimal_precision(num: i64, precision: u8, scale: i8) -> Result<(), ArrowError> {
1440        validate_decimal64_precision(num, precision, scale)
1441    }
1442
1443    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1444        is_validate_decimal64_precision(value, precision)
1445    }
1446}
1447
1448impl ArrowPrimitiveType for Decimal64Type {
1449    type Native = i64;
1450
1451    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1452}
1453
1454impl primitive::PrimitiveTypeSealed for Decimal64Type {}
1455
1456/// The decimal type for a Decimal128Array
1457#[derive(Debug)]
1458pub struct Decimal128Type {}
1459
1460impl DecimalType for Decimal128Type {
1461    const BYTE_LENGTH: usize = 16;
1462    const MAX_PRECISION: u8 = DECIMAL128_MAX_PRECISION;
1463    const MAX_SCALE: i8 = DECIMAL128_MAX_SCALE;
1464    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal128;
1465    const DEFAULT_TYPE: DataType =
1466        DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1467    const PREFIX: &'static str = "Decimal128";
1468
1469    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1470        format_decimal_str(&value.to_string(), precision as usize, scale)
1471    }
1472
1473    fn validate_decimal_precision(num: i128, precision: u8, scale: i8) -> Result<(), ArrowError> {
1474        validate_decimal_precision(num, precision, scale)
1475    }
1476
1477    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1478        is_validate_decimal_precision(value, precision)
1479    }
1480}
1481
1482impl ArrowPrimitiveType for Decimal128Type {
1483    type Native = i128;
1484
1485    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1486}
1487
1488impl primitive::PrimitiveTypeSealed for Decimal128Type {}
1489
1490/// The decimal type for a Decimal256Array
1491#[derive(Debug)]
1492pub struct Decimal256Type {}
1493
1494impl DecimalType for Decimal256Type {
1495    const BYTE_LENGTH: usize = 32;
1496    const MAX_PRECISION: u8 = DECIMAL256_MAX_PRECISION;
1497    const MAX_SCALE: i8 = DECIMAL256_MAX_SCALE;
1498    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal256;
1499    const DEFAULT_TYPE: DataType =
1500        DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1501    const PREFIX: &'static str = "Decimal256";
1502
1503    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1504        format_decimal_str(&value.to_string(), precision as usize, scale)
1505    }
1506
1507    fn validate_decimal_precision(num: i256, precision: u8, scale: i8) -> Result<(), ArrowError> {
1508        validate_decimal256_precision(num, precision, scale)
1509    }
1510
1511    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1512        is_validate_decimal256_precision(value, precision)
1513    }
1514}
1515
1516impl ArrowPrimitiveType for Decimal256Type {
1517    type Native = i256;
1518
1519    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1520}
1521
1522impl primitive::PrimitiveTypeSealed for Decimal256Type {}
1523
1524/// Crate private types for Byte Arrays
1525///
1526/// Not intended to be used outside this crate
1527pub(crate) mod bytes {
1528    use super::*;
1529
1530    pub trait ByteArrayTypeSealed {}
1531    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericStringType<O> {}
1532    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericBinaryType<O> {}
1533
1534    pub trait ByteArrayNativeType: std::fmt::Debug + Send + Sync {
1535        fn from_bytes_checked(b: &[u8]) -> Option<&Self>;
1536
1537        /// # Safety
1538        ///
1539        /// `b` must be a valid byte sequence for `Self`
1540        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self;
1541    }
1542
1543    impl ByteArrayNativeType for [u8] {
1544        #[inline]
1545        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1546            Some(b)
1547        }
1548
1549        #[inline]
1550        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1551            b
1552        }
1553    }
1554
1555    impl ByteArrayNativeType for str {
1556        #[inline]
1557        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1558            std::str::from_utf8(b).ok()
1559        }
1560
1561        #[inline]
1562        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1563            std::str::from_utf8_unchecked(b)
1564        }
1565    }
1566}
1567
1568/// A trait over the variable-size byte array types
1569///
1570/// See [Variable Size Binary Layout](https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout)
1571pub trait ByteArrayType: 'static + Send + Sync + bytes::ByteArrayTypeSealed {
1572    /// Type of offset i.e i32/i64
1573    type Offset: OffsetSizeTrait;
1574    /// Type for representing its equivalent rust type i.e
1575    /// Utf8Array will have native type has &str
1576    /// BinaryArray will have type as [u8]
1577    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1578
1579    /// "Binary" or "String", for use in error messages
1580    const PREFIX: &'static str;
1581
1582    /// Datatype of array elements
1583    const DATA_TYPE: DataType;
1584
1585    /// Verifies that every consecutive pair of `offsets` denotes a valid slice of `values`
1586    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError>;
1587}
1588
1589/// [`ByteArrayType`] for string arrays
1590pub struct GenericStringType<O: OffsetSizeTrait> {
1591    phantom: PhantomData<O>,
1592}
1593
1594impl<O: OffsetSizeTrait> ByteArrayType for GenericStringType<O> {
1595    type Offset = O;
1596    type Native = str;
1597    const PREFIX: &'static str = "String";
1598
1599    const DATA_TYPE: DataType = if O::IS_LARGE {
1600        DataType::LargeUtf8
1601    } else {
1602        DataType::Utf8
1603    };
1604
1605    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1606        // Verify that the slice as a whole is valid UTF-8
1607        let validated = std::str::from_utf8(values).map_err(|e| {
1608            ArrowError::InvalidArgumentError(format!("Encountered non UTF-8 data: {e}"))
1609        })?;
1610
1611        // Verify each offset is at a valid character boundary in this UTF-8 array
1612        for offset in offsets.iter() {
1613            let o = offset.as_usize();
1614            if !validated.is_char_boundary(o) {
1615                if o < validated.len() {
1616                    return Err(ArrowError::InvalidArgumentError(format!(
1617                        "Split UTF-8 codepoint at offset {o}"
1618                    )));
1619                }
1620                return Err(ArrowError::InvalidArgumentError(format!(
1621                    "Offset of {o} exceeds length of values {}",
1622                    validated.len()
1623                )));
1624            }
1625        }
1626        Ok(())
1627    }
1628}
1629
1630/// An arrow utf8 array with i32 offsets
1631pub type Utf8Type = GenericStringType<i32>;
1632/// An arrow utf8 array with i64 offsets
1633pub type LargeUtf8Type = GenericStringType<i64>;
1634
1635/// [`ByteArrayType`] for binary arrays
1636pub struct GenericBinaryType<O: OffsetSizeTrait> {
1637    phantom: PhantomData<O>,
1638}
1639
1640impl<O: OffsetSizeTrait> ByteArrayType for GenericBinaryType<O> {
1641    type Offset = O;
1642    type Native = [u8];
1643    const PREFIX: &'static str = "Binary";
1644
1645    const DATA_TYPE: DataType = if O::IS_LARGE {
1646        DataType::LargeBinary
1647    } else {
1648        DataType::Binary
1649    };
1650
1651    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1652        // offsets are guaranteed to be monotonically increasing and non-empty
1653        let max_offset = offsets.last().unwrap().as_usize();
1654        if values.len() < max_offset {
1655            return Err(ArrowError::InvalidArgumentError(format!(
1656                "Maximum offset of {max_offset} is larger than values of length {}",
1657                values.len()
1658            )));
1659        }
1660        Ok(())
1661    }
1662}
1663
1664/// An arrow binary array with i32 offsets
1665pub type BinaryType = GenericBinaryType<i32>;
1666/// An arrow binary array with i64 offsets
1667pub type LargeBinaryType = GenericBinaryType<i64>;
1668
1669mod byte_view {
1670    use crate::types::{BinaryViewType, StringViewType};
1671
1672    pub trait Sealed: Send + Sync {}
1673    impl Sealed for StringViewType {}
1674    impl Sealed for BinaryViewType {}
1675}
1676
1677/// A trait over the variable length bytes view array types
1678pub trait ByteViewType: byte_view::Sealed + 'static + PartialEq + Send + Sync {
1679    /// If element in array is utf8 encoded string.
1680    const IS_UTF8: bool;
1681
1682    /// Datatype of array elements
1683    const DATA_TYPE: DataType = if Self::IS_UTF8 {
1684        DataType::Utf8View
1685    } else {
1686        DataType::BinaryView
1687    };
1688
1689    /// "Binary" or "String", for use in displayed or error messages
1690    const PREFIX: &'static str;
1691
1692    /// Type for representing its equivalent rust type i.e
1693    /// Utf8Array will have native type has &str
1694    /// BinaryArray will have type as [u8]
1695    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1696
1697    /// Type for owned corresponding to `Native`
1698    type Owned: Debug + Clone + Sync + Send + AsRef<Self::Native>;
1699
1700    /// Verifies that the provided buffers are valid for this array type
1701    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError>;
1702}
1703
1704/// [`ByteViewType`] for string arrays
1705#[derive(PartialEq)]
1706pub struct StringViewType {}
1707
1708impl ByteViewType for StringViewType {
1709    const IS_UTF8: bool = true;
1710    const PREFIX: &'static str = "String";
1711
1712    type Native = str;
1713    type Owned = String;
1714
1715    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1716        validate_string_view(views, buffers)
1717    }
1718}
1719
1720/// [`BinaryViewType`] for string arrays
1721#[derive(PartialEq)]
1722pub struct BinaryViewType {}
1723
1724impl ByteViewType for BinaryViewType {
1725    const IS_UTF8: bool = false;
1726    const PREFIX: &'static str = "Binary";
1727    type Native = [u8];
1728    type Owned = Vec<u8>;
1729
1730    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1731        validate_binary_view(views, buffers)
1732    }
1733}
1734
1735#[cfg(test)]
1736mod tests {
1737    use super::*;
1738    use arrow_data::{layout, BufferSpec};
1739
1740    #[test]
1741    fn month_day_nano_should_roundtrip() {
1742        let value = IntervalMonthDayNanoType::make_value(1, 2, 3);
1743        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (1, 2, 3));
1744    }
1745
1746    #[test]
1747    fn month_day_nano_should_roundtrip_neg() {
1748        let value = IntervalMonthDayNanoType::make_value(-1, -2, -3);
1749        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (-1, -2, -3));
1750    }
1751
1752    #[test]
1753    fn day_time_should_roundtrip() {
1754        let value = IntervalDayTimeType::make_value(1, 2);
1755        assert_eq!(IntervalDayTimeType::to_parts(value), (1, 2));
1756    }
1757
1758    #[test]
1759    fn day_time_should_roundtrip_neg() {
1760        let value = IntervalDayTimeType::make_value(-1, -2);
1761        assert_eq!(IntervalDayTimeType::to_parts(value), (-1, -2));
1762    }
1763
1764    #[test]
1765    fn year_month_should_roundtrip() {
1766        let value = IntervalYearMonthType::make_value(1, 2);
1767        assert_eq!(IntervalYearMonthType::to_months(value), 14);
1768    }
1769
1770    #[test]
1771    fn year_month_should_roundtrip_neg() {
1772        let value = IntervalYearMonthType::make_value(-1, -2);
1773        assert_eq!(IntervalYearMonthType::to_months(value), -14);
1774    }
1775
1776    fn test_layout<T: ArrowPrimitiveType>() {
1777        let layout = layout(&T::DATA_TYPE);
1778
1779        assert_eq!(layout.buffers.len(), 1);
1780
1781        let spec = &layout.buffers[0];
1782        assert_eq!(
1783            spec,
1784            &BufferSpec::FixedWidth {
1785                byte_width: std::mem::size_of::<T::Native>(),
1786                alignment: std::mem::align_of::<T::Native>(),
1787            }
1788        );
1789    }
1790
1791    #[test]
1792    fn test_layouts() {
1793        test_layout::<Int8Type>();
1794        test_layout::<Int16Type>();
1795        test_layout::<Int32Type>();
1796        test_layout::<Int64Type>();
1797        test_layout::<UInt8Type>();
1798        test_layout::<UInt16Type>();
1799        test_layout::<UInt32Type>();
1800        test_layout::<UInt64Type>();
1801        test_layout::<Float16Type>();
1802        test_layout::<Float32Type>();
1803        test_layout::<Float64Type>();
1804        test_layout::<Decimal32Type>();
1805        test_layout::<Decimal64Type>();
1806        test_layout::<Decimal128Type>();
1807        test_layout::<Decimal256Type>();
1808        test_layout::<TimestampNanosecondType>();
1809        test_layout::<TimestampMillisecondType>();
1810        test_layout::<TimestampMicrosecondType>();
1811        test_layout::<TimestampNanosecondType>();
1812        test_layout::<TimestampSecondType>();
1813        test_layout::<Date32Type>();
1814        test_layout::<Date64Type>();
1815        test_layout::<Time32SecondType>();
1816        test_layout::<Time32MillisecondType>();
1817        test_layout::<Time64MicrosecondType>();
1818        test_layout::<Time64NanosecondType>();
1819        test_layout::<IntervalMonthDayNanoType>();
1820        test_layout::<IntervalDayTimeType>();
1821        test_layout::<IntervalYearMonthType>();
1822        test_layout::<DurationNanosecondType>();
1823        test_layout::<DurationMicrosecondType>();
1824        test_layout::<DurationMillisecondType>();
1825        test_layout::<DurationSecondType>();
1826    }
1827}