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    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(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`
1351pub fn validate_decimal_precision_and_scale<T: DecimalType>(
1352    precision: u8,
1353    scale: i8,
1354) -> Result<(), ArrowError> {
1355    if precision == 0 {
1356        return Err(ArrowError::InvalidArgumentError(format!(
1357            "precision cannot be 0, has to be between [1, {}]",
1358            T::MAX_PRECISION
1359        )));
1360    }
1361    if precision > T::MAX_PRECISION {
1362        return Err(ArrowError::InvalidArgumentError(format!(
1363            "precision {} is greater than max {}",
1364            precision,
1365            T::MAX_PRECISION
1366        )));
1367    }
1368    if scale > T::MAX_SCALE {
1369        return Err(ArrowError::InvalidArgumentError(format!(
1370            "scale {} is greater than max {}",
1371            scale,
1372            T::MAX_SCALE
1373        )));
1374    }
1375    if scale > 0 && scale as u8 > precision {
1376        return Err(ArrowError::InvalidArgumentError(format!(
1377            "scale {scale} is greater than precision {precision}"
1378        )));
1379    }
1380
1381    Ok(())
1382}
1383
1384/// The decimal type for a Decimal32Array
1385#[derive(Debug)]
1386pub struct Decimal32Type {}
1387
1388impl 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    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1398        format_decimal_str(&value.to_string(), precision as usize, scale)
1399    }
1400
1401    fn validate_decimal_precision(num: i32, precision: u8) -> Result<(), ArrowError> {
1402        validate_decimal32_precision(num, precision)
1403    }
1404
1405    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1406        is_validate_decimal32_precision(value, precision)
1407    }
1408}
1409
1410impl ArrowPrimitiveType for Decimal32Type {
1411    type Native = i32;
1412
1413    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1414}
1415
1416impl primitive::PrimitiveTypeSealed for Decimal32Type {}
1417
1418/// The decimal type for a Decimal64Array
1419#[derive(Debug)]
1420pub struct Decimal64Type {}
1421
1422impl 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    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1432        format_decimal_str(&value.to_string(), precision as usize, scale)
1433    }
1434
1435    fn validate_decimal_precision(num: i64, precision: u8) -> Result<(), ArrowError> {
1436        validate_decimal64_precision(num, precision)
1437    }
1438
1439    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1440        is_validate_decimal64_precision(value, precision)
1441    }
1442}
1443
1444impl ArrowPrimitiveType for Decimal64Type {
1445    type Native = i64;
1446
1447    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1448}
1449
1450impl primitive::PrimitiveTypeSealed for Decimal64Type {}
1451
1452/// The decimal type for a Decimal128Array
1453#[derive(Debug)]
1454pub struct Decimal128Type {}
1455
1456impl 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    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1466        format_decimal_str(&value.to_string(), precision as usize, scale)
1467    }
1468
1469    fn validate_decimal_precision(num: i128, precision: u8) -> Result<(), ArrowError> {
1470        validate_decimal_precision(num, precision)
1471    }
1472
1473    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1474        is_validate_decimal_precision(value, precision)
1475    }
1476}
1477
1478impl ArrowPrimitiveType for Decimal128Type {
1479    type Native = i128;
1480
1481    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1482}
1483
1484impl primitive::PrimitiveTypeSealed for Decimal128Type {}
1485
1486/// The decimal type for a Decimal256Array
1487#[derive(Debug)]
1488pub struct Decimal256Type {}
1489
1490impl 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    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1500        format_decimal_str(&value.to_string(), precision as usize, scale)
1501    }
1502
1503    fn validate_decimal_precision(num: i256, precision: u8) -> Result<(), ArrowError> {
1504        validate_decimal256_precision(num, precision)
1505    }
1506
1507    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1508        is_validate_decimal256_precision(value, precision)
1509    }
1510}
1511
1512impl ArrowPrimitiveType for Decimal256Type {
1513    type Native = i256;
1514
1515    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1516}
1517
1518impl primitive::PrimitiveTypeSealed for Decimal256Type {}
1519
1520fn format_decimal_str(value_str: &str, precision: usize, scale: i8) -> String {
1521    let (sign, rest) = match value_str.strip_prefix('-') {
1522        Some(stripped) => ("-", stripped),
1523        None => ("", value_str),
1524    };
1525    let bound = precision.min(rest.len()) + sign.len();
1526    let value_str = &value_str[0..bound];
1527
1528    if scale == 0 {
1529        value_str.to_string()
1530    } else if scale < 0 {
1531        let padding = value_str.len() + scale.unsigned_abs() as usize;
1532        format!("{value_str:0<padding$}")
1533    } else if rest.len() > scale as usize {
1534        // Decimal separator is in the middle of the string
1535        let (whole, decimal) = value_str.split_at(value_str.len() - scale as usize);
1536        format!("{whole}.{decimal}")
1537    } else {
1538        // String has to be padded
1539        format!("{}0.{:0>width$}", sign, rest, width = scale as usize)
1540    }
1541}
1542
1543/// Crate private types for Byte Arrays
1544///
1545/// Not intended to be used outside this crate
1546pub(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        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1570            b
1571        }
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        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1582            std::str::from_utf8_unchecked(b)
1583        }
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)
1590pub 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
1609pub struct GenericStringType<O: OffsetSizeTrait> {
1610    phantom: PhantomData<O>,
1611}
1612
1613impl<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    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1625        // Verify that the slice as a whole is valid UTF-8
1626        let validated = std::str::from_utf8(values).map_err(|e| {
1627            ArrowError::InvalidArgumentError(format!("Encountered non UTF-8 data: {e}"))
1628        })?;
1629
1630        // Verify each offset is at a valid character boundary in this UTF-8 array
1631        for offset in offsets.iter() {
1632            let o = offset.as_usize();
1633            if !validated.is_char_boundary(o) {
1634                if o < validated.len() {
1635                    return Err(ArrowError::InvalidArgumentError(format!(
1636                        "Split UTF-8 codepoint at offset {o}"
1637                    )));
1638                }
1639                return Err(ArrowError::InvalidArgumentError(format!(
1640                    "Offset of {o} exceeds length of values {}",
1641                    validated.len()
1642                )));
1643            }
1644        }
1645        Ok(())
1646    }
1647}
1648
1649/// An arrow utf8 array with i32 offsets
1650pub type Utf8Type = GenericStringType<i32>;
1651/// An arrow utf8 array with i64 offsets
1652pub type LargeUtf8Type = GenericStringType<i64>;
1653
1654/// [`ByteArrayType`] for binary arrays
1655pub struct GenericBinaryType<O: OffsetSizeTrait> {
1656    phantom: PhantomData<O>,
1657}
1658
1659impl<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    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1671        // offsets are guaranteed to be monotonically increasing and non-empty
1672        let max_offset = offsets.last().unwrap().as_usize();
1673        if values.len() < max_offset {
1674            return Err(ArrowError::InvalidArgumentError(format!(
1675                "Maximum offset of {max_offset} is larger than values of length {}",
1676                values.len()
1677            )));
1678        }
1679        Ok(())
1680    }
1681}
1682
1683/// An arrow binary array with i32 offsets
1684pub type BinaryType = GenericBinaryType<i32>;
1685/// An arrow binary array with i64 offsets
1686pub type LargeBinaryType = GenericBinaryType<i64>;
1687
1688mod 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
1697pub 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)]
1725pub struct StringViewType {}
1726
1727impl 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    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1735        validate_string_view(views, buffers)
1736    }
1737}
1738
1739/// [`BinaryViewType`] for string arrays
1740#[derive(PartialEq)]
1741pub struct BinaryViewType {}
1742
1743impl 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    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1750        validate_binary_view(views, buffers)
1751    }
1752}
1753
1754#[cfg(test)]
1755mod 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::<Decimal128Type>();
1824        test_layout::<Decimal256Type>();
1825        test_layout::<TimestampNanosecondType>();
1826        test_layout::<TimestampMillisecondType>();
1827        test_layout::<TimestampMicrosecondType>();
1828        test_layout::<TimestampNanosecondType>();
1829        test_layout::<TimestampSecondType>();
1830        test_layout::<Date32Type>();
1831        test_layout::<Date64Type>();
1832        test_layout::<Time32SecondType>();
1833        test_layout::<Time32MillisecondType>();
1834        test_layout::<Time64MicrosecondType>();
1835        test_layout::<Time64NanosecondType>();
1836        test_layout::<IntervalMonthDayNanoType>();
1837        test_layout::<IntervalDayTimeType>();
1838        test_layout::<IntervalYearMonthType>();
1839        test_layout::<DurationNanosecondType>();
1840        test_layout::<DurationMicrosecondType>();
1841        test_layout::<DurationMillisecondType>();
1842        test_layout::<DurationSecondType>();
1843    }
1844}