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_date, add_months_datetime, 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::{Buffer, OffsetBuffer, i256};
27use arrow_data::decimal::{
28    format_decimal_str, is_validate_decimal_precision, is_validate_decimal32_precision,
29    is_validate_decimal64_precision, is_validate_decimal256_precision, validate_decimal_precision,
30    validate_decimal32_precision, validate_decimal64_precision, validate_decimal256_precision,
31};
32use arrow_data::{validate_binary_view, validate_string_view};
33use arrow_schema::{
34    ArrowError, DECIMAL_DEFAULT_SCALE, DECIMAL32_DEFAULT_SCALE, DECIMAL32_MAX_PRECISION,
35    DECIMAL32_MAX_SCALE, DECIMAL64_DEFAULT_SCALE, DECIMAL64_MAX_PRECISION, DECIMAL64_MAX_SCALE,
36    DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE, DECIMAL256_MAX_PRECISION, DECIMAL256_MAX_SCALE,
37    DataType, IntervalUnit, TimeUnit,
38};
39use chrono::{Duration, NaiveDate, NaiveDateTime};
40use half::f16;
41use std::fmt::Debug;
42use std::marker::PhantomData;
43use std::ops::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    #[deprecated(since = "58.0.0", note = "Use to_naive_date_opt instead.")]
908    pub fn to_naive_date(i: <Date32Type as ArrowPrimitiveType>::Native) -> NaiveDate {
909        Self::to_naive_date_opt(i)
910            .unwrap_or_else(|| panic!("Date32Type::to_naive_date overflowed for date: {i}",))
911    }
912
913    /// Converts an arrow Date32Type into a chrono::NaiveDate
914    ///
915    /// # Arguments
916    ///
917    /// * `i` - The Date32Type to convert
918    ///
919    /// Returns `Some(NaiveDate)` if it fits, `None` otherwise.
920    pub fn to_naive_date_opt(i: <Date32Type as ArrowPrimitiveType>::Native) -> Option<NaiveDate> {
921        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
922        Duration::try_days(i as i64).and_then(|d| epoch.checked_add_signed(d))
923    }
924
925    /// Converts a chrono::NaiveDate into an arrow Date32Type
926    ///
927    /// # Arguments
928    ///
929    /// * `d` - The NaiveDate to convert
930    pub fn from_naive_date(d: NaiveDate) -> <Date32Type as ArrowPrimitiveType>::Native {
931        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
932        d.sub(epoch).num_days() as <Date32Type as ArrowPrimitiveType>::Native
933    }
934
935    /// Adds the given IntervalYearMonthType to an arrow Date32Type
936    ///
937    /// # Arguments
938    ///
939    /// * `date` - The date on which to perform the operation
940    /// * `delta` - The interval to add
941    #[deprecated(
942        since = "58.0.0",
943        note = "Use `add_year_months_opt` instead, which returns an Option to handle overflow."
944    )]
945    pub fn add_year_months(
946        date: <Date32Type as ArrowPrimitiveType>::Native,
947        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
948    ) -> <Date32Type as ArrowPrimitiveType>::Native {
949        Self::add_year_months_opt(date, delta).unwrap_or_else(|| {
950            panic!("Date32Type::add_year_months overflowed for date: {date}, delta: {delta}",)
951        })
952    }
953
954    /// Adds the given IntervalYearMonthType to an arrow Date32Type
955    ///
956    /// # Arguments
957    ///
958    /// * `date` - The date on which to perform the operation
959    /// * `delta` - The interval to add
960    ///
961    /// Returns `Some(Date32Type)` if it fits, `None` otherwise.
962    pub fn add_year_months_opt(
963        date: <Date32Type as ArrowPrimitiveType>::Native,
964        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
965    ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
966        let prior = Date32Type::to_naive_date_opt(date)?;
967        let months = IntervalYearMonthType::to_months(delta);
968        let posterior = add_months_date(prior, months)?;
969        Some(Date32Type::from_naive_date(posterior))
970    }
971
972    /// Adds the given IntervalDayTimeType to an arrow Date32Type
973    ///
974    /// # Arguments
975    ///
976    /// * `date` - The date on which to perform the operation
977    /// * `delta` - The interval to add
978    #[deprecated(
979        since = "58.0.0",
980        note = "Use `add_day_time_opt` instead, which returns an Option to handle overflow."
981    )]
982    pub fn add_day_time(
983        date: <Date32Type as ArrowPrimitiveType>::Native,
984        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
985    ) -> <Date32Type as ArrowPrimitiveType>::Native {
986        Self::add_day_time_opt(date, delta).unwrap_or_else(|| {
987            panic!("Date32Type::add_day_time overflowed for date: {date}, delta: {delta:?}",)
988        })
989    }
990
991    /// Adds the given IntervalDayTimeType to an arrow Date32Type
992    ///
993    /// # Arguments
994    ///
995    /// * `date` - The date on which to perform the operation
996    /// * `delta` - The interval to add
997    ///
998    /// Returns `Some(Date32Type)` if it fits, `None` otherwise.
999    pub fn add_day_time_opt(
1000        date: <Date32Type as ArrowPrimitiveType>::Native,
1001        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1002    ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
1003        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1004        let res = Date32Type::to_naive_date_opt(date)?;
1005        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1006        let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?;
1007        Some(Date32Type::from_naive_date(res))
1008    }
1009
1010    /// Adds the given IntervalMonthDayNanoType to an arrow Date32Type
1011    ///
1012    /// # Arguments
1013    ///
1014    /// * `date` - The date on which to perform the operation
1015    /// * `delta` - The interval to add
1016    #[deprecated(
1017        since = "58.0.0",
1018        note = "Use `add_month_day_nano_opt` instead, which returns an Option to handle overflow."
1019    )]
1020    pub fn add_month_day_nano(
1021        date: <Date32Type as ArrowPrimitiveType>::Native,
1022        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1023    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1024        Self::add_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1025            panic!("Date32Type::add_month_day_nano overflowed for date: {date}, delta: {delta:?}",)
1026        })
1027    }
1028
1029    /// Adds the given IntervalMonthDayNanoType to an arrow Date32Type
1030    ///
1031    /// # Arguments
1032    ///
1033    /// * `date` - The date on which to perform the operation
1034    /// * `delta` - The interval to add
1035    ///
1036    /// Returns `Some(Date32Type)` if it fits, `None` otherwise.
1037    pub fn add_month_day_nano_opt(
1038        date: <Date32Type as ArrowPrimitiveType>::Native,
1039        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1040    ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
1041        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1042        let res = Date32Type::to_naive_date_opt(date)?;
1043        let res = add_months_date(res, months)?;
1044        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1045        let res = res.checked_add_signed(Duration::nanoseconds(nanos))?;
1046        Some(Date32Type::from_naive_date(res))
1047    }
1048
1049    /// Subtract the given IntervalYearMonthType to an arrow Date32Type
1050    ///
1051    /// # Arguments
1052    ///
1053    /// * `date` - The date on which to perform the operation
1054    /// * `delta` - The interval to subtract
1055    #[deprecated(
1056        since = "58.0.0",
1057        note = "Use `subtract_year_months_opt` instead, which returns an Option to handle overflow."
1058    )]
1059    pub fn subtract_year_months(
1060        date: <Date32Type as ArrowPrimitiveType>::Native,
1061        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1062    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1063        Self::subtract_year_months_opt(date, delta).unwrap_or_else(|| {
1064            panic!("Date32Type::subtract_year_months overflowed for date: {date}, delta: {delta}",)
1065        })
1066    }
1067
1068    /// Subtract the given IntervalYearMonthType to an arrow Date32Type
1069    ///
1070    /// # Arguments
1071    ///
1072    /// * `date` - The date on which to perform the operation
1073    /// * `delta` - The interval to subtract
1074    ///
1075    /// Returns `Some(Date32Type)` if it fits, `None` otherwise.
1076    pub fn subtract_year_months_opt(
1077        date: <Date32Type as ArrowPrimitiveType>::Native,
1078        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1079    ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
1080        let prior = Date32Type::to_naive_date_opt(date)?;
1081        let months = IntervalYearMonthType::to_months(-delta);
1082        let posterior = add_months_date(prior, months)?;
1083        Some(Date32Type::from_naive_date(posterior))
1084    }
1085
1086    /// Subtract the given IntervalDayTimeType to an arrow Date32Type
1087    ///
1088    /// # Arguments
1089    ///
1090    /// * `date` - The date on which to perform the operation
1091    /// * `delta` - The interval to subtract
1092    #[deprecated(
1093        since = "58.0.0",
1094        note = "Use `subtract_day_time_opt` instead, which returns an Option to handle overflow."
1095    )]
1096    pub fn subtract_day_time(
1097        date: <Date32Type as ArrowPrimitiveType>::Native,
1098        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1099    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1100        Self::subtract_day_time_opt(date, delta).unwrap_or_else(|| {
1101            panic!("Date32Type::subtract_day_time overflowed for date: {date}, delta: {delta:?}",)
1102        })
1103    }
1104
1105    /// Subtract the given IntervalDayTimeType to an arrow Date32Type
1106    ///
1107    /// # Arguments
1108    ///
1109    /// * `date` - The date on which to perform the operation
1110    /// * `delta` - The interval to subtract
1111    ///
1112    /// Returns `Some(Date32Type)` if it fits, `None` otherwise.
1113    pub fn subtract_day_time_opt(
1114        date: <Date32Type as ArrowPrimitiveType>::Native,
1115        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1116    ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
1117        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1118        let res = Date32Type::to_naive_date_opt(date)?;
1119        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1120        let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?;
1121        Some(Date32Type::from_naive_date(res))
1122    }
1123
1124    /// Subtract the given IntervalMonthDayNanoType to an arrow Date32Type
1125    ///
1126    /// # Arguments
1127    ///
1128    /// * `date` - The date on which to perform the operation
1129    /// * `delta` - The interval to subtract
1130    #[deprecated(
1131        since = "58.0.0",
1132        note = "Use `subtract_month_day_nano_opt` instead, which returns an Option to handle overflow."
1133    )]
1134    pub fn subtract_month_day_nano(
1135        date: <Date32Type as ArrowPrimitiveType>::Native,
1136        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1137    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1138        Self::subtract_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1139            panic!(
1140                "Date32Type::subtract_month_day_nano overflowed for date: {date}, delta: {delta:?}",
1141            )
1142        })
1143    }
1144
1145    /// Subtract the given IntervalMonthDayNanoType to an arrow Date32Type
1146    ///
1147    /// # Arguments
1148    ///
1149    /// * `date` - The date on which to perform the operation
1150    /// * `delta` - The interval to subtract
1151    ///
1152    /// Returns `Some(Date32Type)` if it fits, `None` otherwise.
1153    pub fn subtract_month_day_nano_opt(
1154        date: <Date32Type as ArrowPrimitiveType>::Native,
1155        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1156    ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
1157        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1158        let res = Date32Type::to_naive_date_opt(date)?;
1159        let res = add_months_date(res, -months)?;
1160        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1161        let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?;
1162        Some(Date32Type::from_naive_date(res))
1163    }
1164}
1165
1166impl Date64Type {
1167    /// Converts an arrow Date64Type into a chrono::NaiveDate
1168    ///
1169    /// # Arguments
1170    ///
1171    /// * `i` - The Date64Type to convert
1172    #[deprecated(since = "56.0.0", note = "Use to_naive_date_opt instead.")]
1173    pub fn to_naive_date(i: <Date64Type as ArrowPrimitiveType>::Native) -> NaiveDate {
1174        Self::to_naive_date_opt(i)
1175            .unwrap_or_else(|| panic!("Date64Type::to_naive_date overflowed for date: {i}",))
1176    }
1177
1178    /// Converts an arrow Date64Type into a chrono::NaiveDateTime if it fits in the range that chrono::NaiveDateTime can represent.
1179    /// Returns `None` if the calculation would overflow or underflow.
1180    ///
1181    /// 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).
1182    ///
1183    /// # Arguments
1184    ///
1185    /// * `i` - The Date64Type to convert
1186    ///
1187    /// Returns `Some(NaiveDateTime)` if it fits, `None` otherwise.
1188    pub fn to_naive_date_opt(i: <Date64Type as ArrowPrimitiveType>::Native) -> Option<NaiveDate> {
1189        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1190        Duration::try_milliseconds(i).and_then(|d| epoch.checked_add_signed(d))
1191    }
1192
1193    /// Converts a chrono::NaiveDate into an arrow Date64Type
1194    ///
1195    /// # Arguments
1196    ///
1197    /// * `d` - The NaiveDate to convert
1198    pub fn from_naive_date(d: NaiveDate) -> <Date64Type as ArrowPrimitiveType>::Native {
1199        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1200        d.sub(epoch).num_milliseconds() as <Date64Type as ArrowPrimitiveType>::Native
1201    }
1202
1203    /// Adds the given IntervalYearMonthType to an arrow Date64Type
1204    ///
1205    /// # Arguments
1206    ///
1207    /// * `date` - The date on which to perform the operation
1208    /// * `delta` - The interval to add
1209    #[deprecated(
1210        since = "56.0.0",
1211        note = "Use `add_year_months_opt` instead, which returns an Option to handle overflow."
1212    )]
1213    pub fn add_year_months(
1214        date: <Date64Type as ArrowPrimitiveType>::Native,
1215        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1216    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1217        Self::add_year_months_opt(date, delta).unwrap_or_else(|| {
1218            panic!("Date64Type::add_year_months overflowed for date: {date}, delta: {delta}",)
1219        })
1220    }
1221
1222    /// Adds the given IntervalYearMonthType to an arrow Date64Type
1223    ///
1224    /// # Arguments
1225    ///
1226    /// * `date` - The date on which to perform the operation
1227    /// * `delta` - The interval to add
1228    ///
1229    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1230    pub fn add_year_months_opt(
1231        date: <Date64Type as ArrowPrimitiveType>::Native,
1232        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1233    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1234        let prior = Date64Type::to_naive_date_opt(date)?;
1235        let months = IntervalYearMonthType::to_months(delta);
1236        let posterior = add_months_date(prior, months)?;
1237        Some(Date64Type::from_naive_date(posterior))
1238    }
1239
1240    /// Adds the given IntervalDayTimeType to an arrow Date64Type
1241    ///
1242    /// # Arguments
1243    ///
1244    /// * `date` - The date on which to perform the operation
1245    /// * `delta` - The interval to add
1246    #[deprecated(
1247        since = "56.0.0",
1248        note = "Use `add_day_time_opt` instead, which returns an Option to handle overflow."
1249    )]
1250    pub fn add_day_time(
1251        date: <Date64Type as ArrowPrimitiveType>::Native,
1252        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1253    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1254        Self::add_day_time_opt(date, delta).unwrap_or_else(|| {
1255            panic!("Date64Type::add_day_time overflowed for date: {date}, delta: {delta:?}",)
1256        })
1257    }
1258
1259    /// Adds the given IntervalDayTimeType to an arrow Date64Type
1260    ///
1261    /// # Arguments
1262    ///
1263    /// * `date` - The date on which to perform the operation
1264    /// * `delta` - The interval to add
1265    ///
1266    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1267    pub fn add_day_time_opt(
1268        date: <Date64Type as ArrowPrimitiveType>::Native,
1269        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1270    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1271        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1272        let res = Date64Type::to_naive_date_opt(date)?;
1273        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1274        let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?;
1275        Some(Date64Type::from_naive_date(res))
1276    }
1277
1278    /// Adds the given IntervalMonthDayNanoType to an arrow Date64Type
1279    ///
1280    /// # Arguments
1281    ///
1282    /// * `date` - The date on which to perform the operation
1283    /// * `delta` - The interval to add
1284    #[deprecated(
1285        since = "56.0.0",
1286        note = "Use `add_month_day_nano_opt` instead, which returns an Option to handle overflow."
1287    )]
1288    pub fn add_month_day_nano(
1289        date: <Date64Type as ArrowPrimitiveType>::Native,
1290        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1291    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1292        Self::add_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1293            panic!("Date64Type::add_month_day_nano overflowed for date: {date}, delta: {delta:?}",)
1294        })
1295    }
1296
1297    /// Adds the given IntervalMonthDayNanoType to an arrow Date64Type
1298    ///
1299    /// # Arguments
1300    ///
1301    /// * `date` - The date on which to perform the operation
1302    /// * `delta` - The interval to add
1303    ///
1304    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1305    pub fn add_month_day_nano_opt(
1306        date: <Date64Type as ArrowPrimitiveType>::Native,
1307        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1308    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1309        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1310        let res = Date64Type::to_naive_date_opt(date)?;
1311        let res = add_months_date(res, months)?;
1312        let res = res.checked_add_signed(Duration::try_days(days as i64)?)?;
1313        let res = res.checked_add_signed(Duration::nanoseconds(nanos))?;
1314        Some(Date64Type::from_naive_date(res))
1315    }
1316
1317    /// Subtract the given IntervalYearMonthType to an arrow Date64Type
1318    ///
1319    /// # Arguments
1320    ///
1321    /// * `date` - The date on which to perform the operation
1322    /// * `delta` - The interval to subtract
1323    #[deprecated(
1324        since = "56.0.0",
1325        note = "Use `subtract_year_months_opt` instead, which returns an Option to handle overflow."
1326    )]
1327    pub fn subtract_year_months(
1328        date: <Date64Type as ArrowPrimitiveType>::Native,
1329        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1330    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1331        Self::subtract_year_months_opt(date, delta).unwrap_or_else(|| {
1332            panic!("Date64Type::subtract_year_months overflowed for date: {date}, delta: {delta}",)
1333        })
1334    }
1335
1336    /// Subtract the given IntervalYearMonthType to an arrow Date64Type
1337    ///
1338    /// # Arguments
1339    ///
1340    /// * `date` - The date on which to perform the operation
1341    /// * `delta` - The interval to subtract
1342    ///
1343    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1344    pub fn subtract_year_months_opt(
1345        date: <Date64Type as ArrowPrimitiveType>::Native,
1346        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1347    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1348        let prior = Date64Type::to_naive_date_opt(date)?;
1349        let months = IntervalYearMonthType::to_months(-delta);
1350        let posterior = add_months_date(prior, months)?;
1351        Some(Date64Type::from_naive_date(posterior))
1352    }
1353
1354    /// Subtract the given IntervalDayTimeType to an arrow Date64Type
1355    ///
1356    /// # Arguments
1357    ///
1358    /// * `date` - The date on which to perform the operation
1359    /// * `delta` - The interval to subtract
1360    #[deprecated(
1361        since = "56.0.0",
1362        note = "Use `subtract_day_time_opt` instead, which returns an Option to handle overflow."
1363    )]
1364    pub fn subtract_day_time(
1365        date: <Date64Type as ArrowPrimitiveType>::Native,
1366        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1367    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1368        Self::subtract_day_time_opt(date, delta).unwrap_or_else(|| {
1369            panic!("Date64Type::subtract_day_time overflowed for date: {date}, delta: {delta:?}",)
1370        })
1371    }
1372
1373    /// Subtract the given IntervalDayTimeType to an arrow Date64Type
1374    ///
1375    /// # Arguments
1376    ///
1377    /// * `date` - The date on which to perform the operation
1378    /// * `delta` - The interval to subtract
1379    ///
1380    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1381    pub fn subtract_day_time_opt(
1382        date: <Date64Type as ArrowPrimitiveType>::Native,
1383        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1384    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1385        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1386        let res = Date64Type::to_naive_date_opt(date)?;
1387        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1388        let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?;
1389        Some(Date64Type::from_naive_date(res))
1390    }
1391
1392    /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type
1393    ///
1394    /// # Arguments
1395    ///
1396    /// * `date` - The date on which to perform the operation
1397    /// * `delta` - The interval to subtract
1398    #[deprecated(
1399        since = "56.0.0",
1400        note = "Use `subtract_month_day_nano_opt` instead, which returns an Option to handle overflow."
1401    )]
1402    pub fn subtract_month_day_nano(
1403        date: <Date64Type as ArrowPrimitiveType>::Native,
1404        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1405    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1406        Self::subtract_month_day_nano_opt(date, delta).unwrap_or_else(|| {
1407            panic!(
1408                "Date64Type::subtract_month_day_nano overflowed for date: {date}, delta: {delta:?}",
1409            )
1410        })
1411    }
1412
1413    /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type
1414    ///
1415    /// # Arguments
1416    ///
1417    /// * `date` - The date on which to perform the operation
1418    /// * `delta` - The interval to subtract
1419    ///
1420    /// Returns `Some(Date64Type)` if it fits, `None` otherwise.
1421    pub fn subtract_month_day_nano_opt(
1422        date: <Date64Type as ArrowPrimitiveType>::Native,
1423        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1424    ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> {
1425        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1426        let res = Date64Type::to_naive_date_opt(date)?;
1427        let res = add_months_date(res, -months)?;
1428        let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?;
1429        let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?;
1430        Some(Date64Type::from_naive_date(res))
1431    }
1432}
1433
1434/// Crate private types for Decimal Arrays
1435///
1436/// Not intended to be used outside this crate
1437mod decimal {
1438    use super::*;
1439
1440    pub trait DecimalTypeSealed {}
1441    impl DecimalTypeSealed for Decimal32Type {}
1442    impl DecimalTypeSealed for Decimal64Type {}
1443    impl DecimalTypeSealed for Decimal128Type {}
1444    impl DecimalTypeSealed for Decimal256Type {}
1445}
1446
1447/// A trait over the decimal types, used by [`PrimitiveArray`] to provide a generic
1448/// implementation across the various decimal types
1449///
1450/// Implemented by [`Decimal32Type`], [`Decimal64Type`], [`Decimal128Type`] and [`Decimal256Type`]
1451/// for [`Decimal32Array`], [`Decimal64Array`], [`Decimal128Array`] and [`Decimal256Array`] respectively
1452///
1453/// [`PrimitiveArray`]: crate::array::PrimitiveArray
1454/// [`Decimal32Array`]: crate::array::Decimal32Array
1455/// [`Decimal64Array`]: crate::array::Decimal64Array
1456/// [`Decimal128Array`]: crate::array::Decimal128Array
1457/// [`Decimal256Array`]: crate::array::Decimal256Array
1458pub trait DecimalType:
1459    'static + Send + Sync + ArrowPrimitiveType + decimal::DecimalTypeSealed
1460{
1461    /// Width of the type
1462    const BYTE_LENGTH: usize;
1463    /// Maximum number of significant digits
1464    const MAX_PRECISION: u8;
1465    /// Maximum no of digits after the decimal point (note the scale can be negative)
1466    const MAX_SCALE: i8;
1467    /// The maximum value for each precision in `0..=MAX_PRECISION`: [0, 9, 99, ...]
1468    const MAX_FOR_EACH_PRECISION: &'static [Self::Native];
1469    /// fn to create its [`DataType`]
1470    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType;
1471    /// Default values for [`DataType`]
1472    const DEFAULT_TYPE: DataType;
1473
1474    /// "Decimal32", "Decimal64", "Decimal128" or "Decimal256", for use in error messages
1475    const PREFIX: &'static str;
1476
1477    /// Formats the decimal value with the provided precision and scale
1478    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String;
1479
1480    /// Validates that `value` contains no more than `precision` decimal digits
1481    fn validate_decimal_precision(
1482        value: Self::Native,
1483        precision: u8,
1484        scale: i8,
1485    ) -> Result<(), ArrowError>;
1486
1487    /// Determines whether `value` contains no more than `precision` decimal digits
1488    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool;
1489}
1490
1491/// Validate that `precision` and `scale` are valid for `T`
1492///
1493/// Returns an Error if:
1494/// - `precision` is zero
1495/// - `precision` is larger than `T:MAX_PRECISION`
1496/// - `scale` is larger than `T::MAX_SCALE`
1497/// - `scale` is > `precision`
1498pub fn validate_decimal_precision_and_scale<T: DecimalType>(
1499    precision: u8,
1500    scale: i8,
1501) -> Result<(), ArrowError> {
1502    if precision == 0 {
1503        return Err(ArrowError::InvalidArgumentError(format!(
1504            "precision cannot be 0, has to be between [1, {}]",
1505            T::MAX_PRECISION
1506        )));
1507    }
1508    if precision > T::MAX_PRECISION {
1509        return Err(ArrowError::InvalidArgumentError(format!(
1510            "precision {} is greater than max {}",
1511            precision,
1512            T::MAX_PRECISION
1513        )));
1514    }
1515    if scale > T::MAX_SCALE {
1516        return Err(ArrowError::InvalidArgumentError(format!(
1517            "scale {} is greater than max {}",
1518            scale,
1519            T::MAX_SCALE
1520        )));
1521    }
1522    if scale > 0 && scale as u8 > precision {
1523        return Err(ArrowError::InvalidArgumentError(format!(
1524            "scale {scale} is greater than precision {precision}"
1525        )));
1526    }
1527
1528    Ok(())
1529}
1530
1531/// The decimal type for a Decimal32Array
1532#[derive(Debug)]
1533pub struct Decimal32Type {}
1534
1535impl DecimalType for Decimal32Type {
1536    const BYTE_LENGTH: usize = 4;
1537    const MAX_PRECISION: u8 = DECIMAL32_MAX_PRECISION;
1538    const MAX_SCALE: i8 = DECIMAL32_MAX_SCALE;
1539    const MAX_FOR_EACH_PRECISION: &'static [i32] =
1540        &arrow_data::decimal::MAX_DECIMAL32_FOR_EACH_PRECISION;
1541    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal32;
1542    const DEFAULT_TYPE: DataType =
1543        DataType::Decimal32(DECIMAL32_MAX_PRECISION, DECIMAL32_DEFAULT_SCALE);
1544    const PREFIX: &'static str = "Decimal32";
1545
1546    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1547        format_decimal_str(&value.to_string(), precision as usize, scale)
1548    }
1549
1550    fn validate_decimal_precision(num: i32, precision: u8, scale: i8) -> Result<(), ArrowError> {
1551        validate_decimal32_precision(num, precision, scale)
1552    }
1553
1554    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1555        is_validate_decimal32_precision(value, precision)
1556    }
1557}
1558
1559impl ArrowPrimitiveType for Decimal32Type {
1560    type Native = i32;
1561
1562    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1563}
1564
1565impl primitive::PrimitiveTypeSealed for Decimal32Type {}
1566
1567/// The decimal type for a Decimal64Array
1568#[derive(Debug)]
1569pub struct Decimal64Type {}
1570
1571impl DecimalType for Decimal64Type {
1572    const BYTE_LENGTH: usize = 8;
1573    const MAX_PRECISION: u8 = DECIMAL64_MAX_PRECISION;
1574    const MAX_SCALE: i8 = DECIMAL64_MAX_SCALE;
1575    const MAX_FOR_EACH_PRECISION: &'static [i64] =
1576        &arrow_data::decimal::MAX_DECIMAL64_FOR_EACH_PRECISION;
1577    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal64;
1578    const DEFAULT_TYPE: DataType =
1579        DataType::Decimal64(DECIMAL64_MAX_PRECISION, DECIMAL64_DEFAULT_SCALE);
1580    const PREFIX: &'static str = "Decimal64";
1581
1582    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1583        format_decimal_str(&value.to_string(), precision as usize, scale)
1584    }
1585
1586    fn validate_decimal_precision(num: i64, precision: u8, scale: i8) -> Result<(), ArrowError> {
1587        validate_decimal64_precision(num, precision, scale)
1588    }
1589
1590    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1591        is_validate_decimal64_precision(value, precision)
1592    }
1593}
1594
1595impl ArrowPrimitiveType for Decimal64Type {
1596    type Native = i64;
1597
1598    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1599}
1600
1601impl primitive::PrimitiveTypeSealed for Decimal64Type {}
1602
1603/// The decimal type for a Decimal128Array
1604#[derive(Debug)]
1605pub struct Decimal128Type {}
1606
1607impl DecimalType for Decimal128Type {
1608    const BYTE_LENGTH: usize = 16;
1609    const MAX_PRECISION: u8 = DECIMAL128_MAX_PRECISION;
1610    const MAX_SCALE: i8 = DECIMAL128_MAX_SCALE;
1611    const MAX_FOR_EACH_PRECISION: &'static [i128] =
1612        &arrow_data::decimal::MAX_DECIMAL128_FOR_EACH_PRECISION;
1613    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal128;
1614    const DEFAULT_TYPE: DataType =
1615        DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1616    const PREFIX: &'static str = "Decimal128";
1617
1618    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1619        format_decimal_str(&value.to_string(), precision as usize, scale)
1620    }
1621
1622    fn validate_decimal_precision(num: i128, precision: u8, scale: i8) -> Result<(), ArrowError> {
1623        validate_decimal_precision(num, precision, scale)
1624    }
1625
1626    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1627        is_validate_decimal_precision(value, precision)
1628    }
1629}
1630
1631impl ArrowPrimitiveType for Decimal128Type {
1632    type Native = i128;
1633
1634    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1635}
1636
1637impl primitive::PrimitiveTypeSealed for Decimal128Type {}
1638
1639/// The decimal type for a Decimal256Array
1640#[derive(Debug)]
1641pub struct Decimal256Type {}
1642
1643impl DecimalType for Decimal256Type {
1644    const BYTE_LENGTH: usize = 32;
1645    const MAX_PRECISION: u8 = DECIMAL256_MAX_PRECISION;
1646    const MAX_SCALE: i8 = DECIMAL256_MAX_SCALE;
1647    const MAX_FOR_EACH_PRECISION: &'static [i256] =
1648        &arrow_data::decimal::MAX_DECIMAL256_FOR_EACH_PRECISION;
1649    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal256;
1650    const DEFAULT_TYPE: DataType =
1651        DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1652    const PREFIX: &'static str = "Decimal256";
1653
1654    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1655        format_decimal_str(&value.to_string(), precision as usize, scale)
1656    }
1657
1658    fn validate_decimal_precision(num: i256, precision: u8, scale: i8) -> Result<(), ArrowError> {
1659        validate_decimal256_precision(num, precision, scale)
1660    }
1661
1662    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1663        is_validate_decimal256_precision(value, precision)
1664    }
1665}
1666
1667impl ArrowPrimitiveType for Decimal256Type {
1668    type Native = i256;
1669
1670    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1671}
1672
1673impl primitive::PrimitiveTypeSealed for Decimal256Type {}
1674
1675/// Crate private types for Byte Arrays
1676///
1677/// Not intended to be used outside this crate
1678pub(crate) mod bytes {
1679    use super::*;
1680
1681    pub trait ByteArrayTypeSealed {}
1682    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericStringType<O> {}
1683    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericBinaryType<O> {}
1684
1685    pub trait ByteArrayNativeType: std::fmt::Debug + Send + Sync {
1686        fn from_bytes_checked(b: &[u8]) -> Option<&Self>;
1687
1688        /// # Safety
1689        ///
1690        /// `b` must be a valid byte sequence for `Self`
1691        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self;
1692    }
1693
1694    impl ByteArrayNativeType for [u8] {
1695        #[inline]
1696        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1697            Some(b)
1698        }
1699
1700        #[inline]
1701        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1702            b
1703        }
1704    }
1705
1706    impl ByteArrayNativeType for str {
1707        #[inline]
1708        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1709            std::str::from_utf8(b).ok()
1710        }
1711
1712        #[inline]
1713        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1714            unsafe { std::str::from_utf8_unchecked(b) }
1715        }
1716    }
1717}
1718
1719/// A trait over the variable-size byte array types
1720///
1721/// See [Variable Size Binary Layout](https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout)
1722pub trait ByteArrayType: 'static + Send + Sync + bytes::ByteArrayTypeSealed {
1723    /// Type of offset i.e i32/i64
1724    type Offset: OffsetSizeTrait;
1725    /// Type for representing its equivalent rust type i.e
1726    /// Utf8Array will have native type has &str
1727    /// BinaryArray will have type as [u8]
1728    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1729
1730    /// "Binary" or "String", for use in error messages
1731    const PREFIX: &'static str;
1732
1733    /// Datatype of array elements
1734    const DATA_TYPE: DataType;
1735
1736    /// Verifies that every consecutive pair of `offsets` denotes a valid slice of `values`
1737    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError>;
1738}
1739
1740/// [`ByteArrayType`] for string arrays
1741pub struct GenericStringType<O: OffsetSizeTrait> {
1742    phantom: PhantomData<O>,
1743}
1744
1745impl<O: OffsetSizeTrait> ByteArrayType for GenericStringType<O> {
1746    type Offset = O;
1747    type Native = str;
1748    const PREFIX: &'static str = "String";
1749
1750    const DATA_TYPE: DataType = if O::IS_LARGE {
1751        DataType::LargeUtf8
1752    } else {
1753        DataType::Utf8
1754    };
1755
1756    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1757        // Verify that the slice as a whole is valid UTF-8
1758        let validated = std::str::from_utf8(values).map_err(|e| {
1759            ArrowError::InvalidArgumentError(format!("Encountered non UTF-8 data: {e}"))
1760        })?;
1761
1762        // Verify each offset is at a valid character boundary in this UTF-8 array
1763        for offset in offsets.iter() {
1764            let o = offset.as_usize();
1765            if !validated.is_char_boundary(o) {
1766                if o < validated.len() {
1767                    return Err(ArrowError::InvalidArgumentError(format!(
1768                        "Split UTF-8 codepoint at offset {o}"
1769                    )));
1770                }
1771                return Err(ArrowError::InvalidArgumentError(format!(
1772                    "Offset of {o} exceeds length of values {}",
1773                    validated.len()
1774                )));
1775            }
1776        }
1777        Ok(())
1778    }
1779}
1780
1781/// An arrow utf8 array with i32 offsets
1782pub type Utf8Type = GenericStringType<i32>;
1783/// An arrow utf8 array with i64 offsets
1784pub type LargeUtf8Type = GenericStringType<i64>;
1785
1786/// [`ByteArrayType`] for binary arrays
1787pub struct GenericBinaryType<O: OffsetSizeTrait> {
1788    phantom: PhantomData<O>,
1789}
1790
1791impl<O: OffsetSizeTrait> ByteArrayType for GenericBinaryType<O> {
1792    type Offset = O;
1793    type Native = [u8];
1794    const PREFIX: &'static str = "Binary";
1795
1796    const DATA_TYPE: DataType = if O::IS_LARGE {
1797        DataType::LargeBinary
1798    } else {
1799        DataType::Binary
1800    };
1801
1802    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1803        // offsets are guaranteed to be monotonically increasing and non-empty
1804        let max_offset = offsets.last().unwrap().as_usize();
1805        if values.len() < max_offset {
1806            return Err(ArrowError::InvalidArgumentError(format!(
1807                "Maximum offset of {max_offset} is larger than values of length {}",
1808                values.len()
1809            )));
1810        }
1811        Ok(())
1812    }
1813}
1814
1815/// An arrow binary array with i32 offsets
1816pub type BinaryType = GenericBinaryType<i32>;
1817/// An arrow binary array with i64 offsets
1818pub type LargeBinaryType = GenericBinaryType<i64>;
1819
1820mod byte_view {
1821    use crate::types::{BinaryViewType, StringViewType};
1822
1823    pub trait Sealed: Send + Sync {}
1824    impl Sealed for StringViewType {}
1825    impl Sealed for BinaryViewType {}
1826}
1827
1828/// A trait over the variable length bytes view array types
1829pub trait ByteViewType: byte_view::Sealed + 'static + PartialEq + Send + Sync {
1830    /// If element in array is utf8 encoded string.
1831    const IS_UTF8: bool;
1832
1833    /// Datatype of array elements
1834    const DATA_TYPE: DataType = if Self::IS_UTF8 {
1835        DataType::Utf8View
1836    } else {
1837        DataType::BinaryView
1838    };
1839
1840    /// "Binary" or "String", for use in displayed or error messages
1841    const PREFIX: &'static str;
1842
1843    /// Type for representing its equivalent rust type i.e
1844    /// Utf8Array will have native type has &str
1845    /// BinaryArray will have type as [u8]
1846    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1847
1848    /// Type for owned corresponding to `Native`
1849    type Owned: Debug + Clone + Sync + Send + AsRef<Self::Native>;
1850
1851    /// Verifies that the provided buffers are valid for this array type
1852    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError>;
1853}
1854
1855/// [`ByteViewType`] for string arrays
1856#[derive(PartialEq)]
1857pub struct StringViewType {}
1858
1859impl ByteViewType for StringViewType {
1860    const IS_UTF8: bool = true;
1861    const PREFIX: &'static str = "String";
1862
1863    type Native = str;
1864    type Owned = String;
1865
1866    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1867        validate_string_view(views, buffers)
1868    }
1869}
1870
1871/// [`BinaryViewType`] for string arrays
1872#[derive(PartialEq)]
1873pub struct BinaryViewType {}
1874
1875impl ByteViewType for BinaryViewType {
1876    const IS_UTF8: bool = false;
1877    const PREFIX: &'static str = "Binary";
1878    type Native = [u8];
1879    type Owned = Vec<u8>;
1880
1881    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1882        validate_binary_view(views, buffers)
1883    }
1884}
1885
1886#[cfg(test)]
1887mod tests {
1888    use super::*;
1889    use arrow_data::{BufferSpec, layout};
1890
1891    #[test]
1892    fn month_day_nano_should_roundtrip() {
1893        let value = IntervalMonthDayNanoType::make_value(1, 2, 3);
1894        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (1, 2, 3));
1895    }
1896
1897    #[test]
1898    fn month_day_nano_should_roundtrip_neg() {
1899        let value = IntervalMonthDayNanoType::make_value(-1, -2, -3);
1900        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (-1, -2, -3));
1901    }
1902
1903    #[test]
1904    fn day_time_should_roundtrip() {
1905        let value = IntervalDayTimeType::make_value(1, 2);
1906        assert_eq!(IntervalDayTimeType::to_parts(value), (1, 2));
1907    }
1908
1909    #[test]
1910    fn day_time_should_roundtrip_neg() {
1911        let value = IntervalDayTimeType::make_value(-1, -2);
1912        assert_eq!(IntervalDayTimeType::to_parts(value), (-1, -2));
1913    }
1914
1915    #[test]
1916    fn year_month_should_roundtrip() {
1917        let value = IntervalYearMonthType::make_value(1, 2);
1918        assert_eq!(IntervalYearMonthType::to_months(value), 14);
1919    }
1920
1921    #[test]
1922    fn year_month_should_roundtrip_neg() {
1923        let value = IntervalYearMonthType::make_value(-1, -2);
1924        assert_eq!(IntervalYearMonthType::to_months(value), -14);
1925    }
1926
1927    fn test_layout<T: ArrowPrimitiveType>() {
1928        let layout = layout(&T::DATA_TYPE);
1929
1930        assert_eq!(layout.buffers.len(), 1);
1931
1932        let spec = &layout.buffers[0];
1933        assert_eq!(
1934            spec,
1935            &BufferSpec::FixedWidth {
1936                byte_width: std::mem::size_of::<T::Native>(),
1937                alignment: std::mem::align_of::<T::Native>(),
1938            }
1939        );
1940    }
1941
1942    #[test]
1943    fn test_layouts() {
1944        test_layout::<Int8Type>();
1945        test_layout::<Int16Type>();
1946        test_layout::<Int32Type>();
1947        test_layout::<Int64Type>();
1948        test_layout::<UInt8Type>();
1949        test_layout::<UInt16Type>();
1950        test_layout::<UInt32Type>();
1951        test_layout::<UInt64Type>();
1952        test_layout::<Float16Type>();
1953        test_layout::<Float32Type>();
1954        test_layout::<Float64Type>();
1955        test_layout::<Decimal32Type>();
1956        test_layout::<Decimal64Type>();
1957        test_layout::<Decimal128Type>();
1958        test_layout::<Decimal256Type>();
1959        test_layout::<TimestampNanosecondType>();
1960        test_layout::<TimestampMillisecondType>();
1961        test_layout::<TimestampMicrosecondType>();
1962        test_layout::<TimestampNanosecondType>();
1963        test_layout::<TimestampSecondType>();
1964        test_layout::<Date32Type>();
1965        test_layout::<Date64Type>();
1966        test_layout::<Time32SecondType>();
1967        test_layout::<Time32MillisecondType>();
1968        test_layout::<Time64MicrosecondType>();
1969        test_layout::<Time64NanosecondType>();
1970        test_layout::<IntervalMonthDayNanoType>();
1971        test_layout::<IntervalDayTimeType>();
1972        test_layout::<IntervalYearMonthType>();
1973        test_layout::<DurationNanosecondType>();
1974        test_layout::<DurationMicrosecondType>();
1975        test_layout::<DurationMillisecondType>();
1976        test_layout::<DurationSecondType>();
1977    }
1978}