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_decimal_precision, validate_decimal256_precision,
29    validate_decimal_precision,
30};
31use arrow_data::{validate_binary_view, validate_string_view};
32use arrow_schema::{
33    ArrowError, DataType, IntervalUnit, TimeUnit, DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE,
34    DECIMAL256_MAX_PRECISION, DECIMAL256_MAX_SCALE, DECIMAL_DEFAULT_SCALE,
35};
36use chrono::{Duration, NaiveDate, NaiveDateTime};
37use half::f16;
38use std::fmt::Debug;
39use std::marker::PhantomData;
40use std::ops::{Add, Sub};
41
42// re-export types so that they can be used without importing arrow_buffer explicitly
43pub use arrow_buffer::{IntervalDayTime, IntervalMonthDayNano};
44
45// BooleanType is special: its bit-width is not the size of the primitive type, and its `index`
46// operation assumes bit-packing.
47/// A boolean datatype
48#[derive(Debug)]
49pub struct BooleanType {}
50
51impl BooleanType {
52    /// The corresponding Arrow data type
53    pub const DATA_TYPE: DataType = DataType::Boolean;
54}
55
56/// Trait for [primitive values].
57///
58/// This trait bridges the dynamic-typed nature of Arrow
59/// (via [`DataType`]) with the static-typed nature of rust types
60/// ([`ArrowNativeType`]) for all types that implement [`ArrowNativeType`].
61///
62/// [primitive values]: https://arrow.apache.org/docs/format/Columnar.html#fixed-size-primitive-layout
63/// [`ArrowNativeType`]: arrow_buffer::ArrowNativeType
64pub trait ArrowPrimitiveType: primitive::PrimitiveTypeSealed + 'static {
65    /// Corresponding Rust native type for the primitive type.
66    type Native: ArrowNativeTypeOp;
67
68    /// the corresponding Arrow data type of this primitive type.
69    const DATA_TYPE: DataType;
70
71    /// Returns the byte width of this primitive type.
72    #[deprecated(note = "Use ArrowNativeType::get_byte_width")]
73    fn get_byte_width() -> usize {
74        std::mem::size_of::<Self::Native>()
75    }
76
77    /// Returns a default value of this primitive type.
78    ///
79    /// This is useful for aggregate array ops like `sum()`, `mean()`.
80    fn default_value() -> Self::Native {
81        Default::default()
82    }
83}
84
85mod primitive {
86    pub trait PrimitiveTypeSealed {}
87}
88
89macro_rules! make_type {
90    ($name:ident, $native_ty:ty, $data_ty:expr, $doc_string: literal) => {
91        #[derive(Debug)]
92        #[doc = $doc_string]
93        pub struct $name {}
94
95        impl ArrowPrimitiveType for $name {
96            type Native = $native_ty;
97            const DATA_TYPE: DataType = $data_ty;
98        }
99
100        impl primitive::PrimitiveTypeSealed for $name {}
101    };
102}
103
104make_type!(Int8Type, i8, DataType::Int8, "A signed 8-bit integer type.");
105make_type!(
106    Int16Type,
107    i16,
108    DataType::Int16,
109    "Signed 16-bit integer type."
110);
111make_type!(
112    Int32Type,
113    i32,
114    DataType::Int32,
115    "Signed 32-bit integer type."
116);
117make_type!(
118    Int64Type,
119    i64,
120    DataType::Int64,
121    "Signed 64-bit integer type."
122);
123make_type!(
124    UInt8Type,
125    u8,
126    DataType::UInt8,
127    "Unsigned 8-bit integer type."
128);
129make_type!(
130    UInt16Type,
131    u16,
132    DataType::UInt16,
133    "Unsigned 16-bit integer type."
134);
135make_type!(
136    UInt32Type,
137    u32,
138    DataType::UInt32,
139    "Unsigned 32-bit integer type."
140);
141make_type!(
142    UInt64Type,
143    u64,
144    DataType::UInt64,
145    "Unsigned 64-bit integer type."
146);
147make_type!(
148    Float16Type,
149    f16,
150    DataType::Float16,
151    "16-bit floating point number type."
152);
153make_type!(
154    Float32Type,
155    f32,
156    DataType::Float32,
157    "32-bit floating point number type."
158);
159make_type!(
160    Float64Type,
161    f64,
162    DataType::Float64,
163    "64-bit floating point number type."
164);
165make_type!(
166    TimestampSecondType,
167    i64,
168    DataType::Timestamp(TimeUnit::Second, None),
169    "Timestamp second type with an optional timezone."
170);
171make_type!(
172    TimestampMillisecondType,
173    i64,
174    DataType::Timestamp(TimeUnit::Millisecond, None),
175    "Timestamp millisecond type with an optional timezone."
176);
177make_type!(
178    TimestampMicrosecondType,
179    i64,
180    DataType::Timestamp(TimeUnit::Microsecond, None),
181    "Timestamp microsecond type with an optional timezone."
182);
183make_type!(
184    TimestampNanosecondType,
185    i64,
186    DataType::Timestamp(TimeUnit::Nanosecond, None),
187    "Timestamp nanosecond type with an optional timezone."
188);
189make_type!(
190    Date32Type,
191    i32,
192    DataType::Date32,
193    "32-bit date type: the elapsed time since UNIX epoch in days (32 bits)."
194);
195make_type!(
196    Date64Type,
197    i64,
198    DataType::Date64,
199    "64-bit date type: the elapsed time since UNIX epoch in milliseconds (64 bits). \
200    Values must be divisible by `86_400_000`. \
201    See [`DataType::Date64`] for more details."
202);
203make_type!(
204    Time32SecondType,
205    i32,
206    DataType::Time32(TimeUnit::Second),
207    "32-bit time type: the elapsed time since midnight in seconds."
208);
209make_type!(
210    Time32MillisecondType,
211    i32,
212    DataType::Time32(TimeUnit::Millisecond),
213    "32-bit time type: the elapsed time since midnight in milliseconds."
214);
215make_type!(
216    Time64MicrosecondType,
217    i64,
218    DataType::Time64(TimeUnit::Microsecond),
219    "64-bit time type: the elapsed time since midnight in microseconds."
220);
221make_type!(
222    Time64NanosecondType,
223    i64,
224    DataType::Time64(TimeUnit::Nanosecond),
225    "64-bit time type: the elapsed time since midnight in nanoseconds."
226);
227make_type!(
228    IntervalYearMonthType,
229    i32,
230    DataType::Interval(IntervalUnit::YearMonth),
231    "32-bit “calendar” interval type: the number of whole months."
232);
233make_type!(
234    IntervalDayTimeType,
235    IntervalDayTime,
236    DataType::Interval(IntervalUnit::DayTime),
237    "“Calendar” interval type: days and milliseconds. See [`IntervalDayTime`] for more details."
238);
239make_type!(
240    IntervalMonthDayNanoType,
241    IntervalMonthDayNano,
242    DataType::Interval(IntervalUnit::MonthDayNano),
243    r"“Calendar” interval type: months, days, and nanoseconds. See [`IntervalMonthDayNano`] for more details."
244);
245make_type!(
246    DurationSecondType,
247    i64,
248    DataType::Duration(TimeUnit::Second),
249    "Elapsed time type: seconds."
250);
251make_type!(
252    DurationMillisecondType,
253    i64,
254    DataType::Duration(TimeUnit::Millisecond),
255    "Elapsed time type: milliseconds."
256);
257make_type!(
258    DurationMicrosecondType,
259    i64,
260    DataType::Duration(TimeUnit::Microsecond),
261    "Elapsed time type: microseconds."
262);
263make_type!(
264    DurationNanosecondType,
265    i64,
266    DataType::Duration(TimeUnit::Nanosecond),
267    "Elapsed time type: nanoseconds."
268);
269
270/// A subtype of primitive type that represents legal dictionary keys.
271/// See <https://arrow.apache.org/docs/format/Columnar.html>
272pub trait ArrowDictionaryKeyType: ArrowPrimitiveType {}
273
274impl ArrowDictionaryKeyType for Int8Type {}
275
276impl ArrowDictionaryKeyType for Int16Type {}
277
278impl ArrowDictionaryKeyType for Int32Type {}
279
280impl ArrowDictionaryKeyType for Int64Type {}
281
282impl ArrowDictionaryKeyType for UInt8Type {}
283
284impl ArrowDictionaryKeyType for UInt16Type {}
285
286impl ArrowDictionaryKeyType for UInt32Type {}
287
288impl ArrowDictionaryKeyType for UInt64Type {}
289
290/// A subtype of primitive type that is used as run-ends index
291/// in `RunArray`.
292/// See <https://arrow.apache.org/docs/format/Columnar.html>
293pub trait RunEndIndexType: ArrowPrimitiveType {}
294
295impl RunEndIndexType for Int16Type {}
296
297impl RunEndIndexType for Int32Type {}
298
299impl RunEndIndexType for Int64Type {}
300
301/// A subtype of primitive type that represents temporal values.
302pub trait ArrowTemporalType: ArrowPrimitiveType {}
303
304impl ArrowTemporalType for TimestampSecondType {}
305impl ArrowTemporalType for TimestampMillisecondType {}
306impl ArrowTemporalType for TimestampMicrosecondType {}
307impl ArrowTemporalType for TimestampNanosecondType {}
308impl ArrowTemporalType for Date32Type {}
309impl ArrowTemporalType for Date64Type {}
310impl ArrowTemporalType for Time32SecondType {}
311impl ArrowTemporalType for Time32MillisecondType {}
312impl ArrowTemporalType for Time64MicrosecondType {}
313impl ArrowTemporalType for Time64NanosecondType {}
314// impl ArrowTemporalType for IntervalYearMonthType {}
315// impl ArrowTemporalType for IntervalDayTimeType {}
316// impl ArrowTemporalType for IntervalMonthDayNanoType {}
317impl ArrowTemporalType for DurationSecondType {}
318impl ArrowTemporalType for DurationMillisecondType {}
319impl ArrowTemporalType for DurationMicrosecondType {}
320impl ArrowTemporalType for DurationNanosecondType {}
321
322/// A timestamp type allows us to create array builders that take a timestamp.
323pub trait ArrowTimestampType: ArrowTemporalType<Native = i64> {
324    /// The [`TimeUnit`] of this timestamp.
325    const UNIT: TimeUnit;
326
327    /// Returns the `TimeUnit` of this timestamp.
328    #[deprecated(note = "Use Self::UNIT")]
329    fn get_time_unit() -> TimeUnit {
330        Self::UNIT
331    }
332
333    /// Creates a ArrowTimestampType::Native from the provided [`NaiveDateTime`]
334    ///
335    /// See [`DataType::Timestamp`] for more information on timezone handling
336    fn make_value(naive: NaiveDateTime) -> Option<i64>;
337}
338
339impl ArrowTimestampType for TimestampSecondType {
340    const UNIT: TimeUnit = TimeUnit::Second;
341
342    fn make_value(naive: NaiveDateTime) -> Option<i64> {
343        Some(naive.and_utc().timestamp())
344    }
345}
346impl ArrowTimestampType for TimestampMillisecondType {
347    const UNIT: TimeUnit = TimeUnit::Millisecond;
348
349    fn make_value(naive: NaiveDateTime) -> Option<i64> {
350        let utc = naive.and_utc();
351        let millis = utc.timestamp().checked_mul(1_000)?;
352        millis.checked_add(utc.timestamp_subsec_millis() as i64)
353    }
354}
355impl ArrowTimestampType for TimestampMicrosecondType {
356    const UNIT: TimeUnit = TimeUnit::Microsecond;
357
358    fn make_value(naive: NaiveDateTime) -> Option<i64> {
359        let utc = naive.and_utc();
360        let micros = utc.timestamp().checked_mul(1_000_000)?;
361        micros.checked_add(utc.timestamp_subsec_micros() as i64)
362    }
363}
364impl ArrowTimestampType for TimestampNanosecondType {
365    const UNIT: TimeUnit = TimeUnit::Nanosecond;
366
367    fn make_value(naive: NaiveDateTime) -> Option<i64> {
368        let utc = naive.and_utc();
369        let nanos = utc.timestamp().checked_mul(1_000_000_000)?;
370        nanos.checked_add(utc.timestamp_subsec_nanos() as i64)
371    }
372}
373
374fn add_year_months<T: ArrowTimestampType>(
375    timestamp: <T as ArrowPrimitiveType>::Native,
376    delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
377    tz: Tz,
378) -> Option<<T as ArrowPrimitiveType>::Native> {
379    let months = IntervalYearMonthType::to_months(delta);
380    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
381    let res = add_months_datetime(res, months)?;
382    let res = res.naive_utc();
383    T::make_value(res)
384}
385
386fn add_day_time<T: ArrowTimestampType>(
387    timestamp: <T as ArrowPrimitiveType>::Native,
388    delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
389    tz: Tz,
390) -> Option<<T as ArrowPrimitiveType>::Native> {
391    let (days, ms) = IntervalDayTimeType::to_parts(delta);
392    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
393    let res = add_days_datetime(res, days)?;
394    let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?;
395    let res = res.naive_utc();
396    T::make_value(res)
397}
398
399fn add_month_day_nano<T: ArrowTimestampType>(
400    timestamp: <T as ArrowPrimitiveType>::Native,
401    delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
402    tz: Tz,
403) -> Option<<T as ArrowPrimitiveType>::Native> {
404    let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
405    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
406    let res = add_months_datetime(res, months)?;
407    let res = add_days_datetime(res, days)?;
408    let res = res.checked_add_signed(Duration::nanoseconds(nanos))?;
409    let res = res.naive_utc();
410    T::make_value(res)
411}
412
413fn subtract_year_months<T: ArrowTimestampType>(
414    timestamp: <T as ArrowPrimitiveType>::Native,
415    delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
416    tz: Tz,
417) -> Option<<T as ArrowPrimitiveType>::Native> {
418    let months = IntervalYearMonthType::to_months(delta);
419    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
420    let res = sub_months_datetime(res, months)?;
421    let res = res.naive_utc();
422    T::make_value(res)
423}
424
425fn subtract_day_time<T: ArrowTimestampType>(
426    timestamp: <T as ArrowPrimitiveType>::Native,
427    delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
428    tz: Tz,
429) -> Option<<T as ArrowPrimitiveType>::Native> {
430    let (days, ms) = IntervalDayTimeType::to_parts(delta);
431    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
432    let res = sub_days_datetime(res, days)?;
433    let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?;
434    let res = res.naive_utc();
435    T::make_value(res)
436}
437
438fn subtract_month_day_nano<T: ArrowTimestampType>(
439    timestamp: <T as ArrowPrimitiveType>::Native,
440    delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
441    tz: Tz,
442) -> Option<<T as ArrowPrimitiveType>::Native> {
443    let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
444    let res = as_datetime_with_timezone::<T>(timestamp, tz)?;
445    let res = sub_months_datetime(res, months)?;
446    let res = sub_days_datetime(res, days)?;
447    let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?;
448    let res = res.naive_utc();
449    T::make_value(res)
450}
451
452impl TimestampSecondType {
453    /// Adds the given IntervalYearMonthType to an arrow TimestampSecondType.
454    ///
455    /// Returns `None` when it will result in overflow.
456    ///
457    /// # Arguments
458    ///
459    /// * `timestamp` - The date on which to perform the operation
460    /// * `delta` - The interval to add
461    /// * `tz` - The timezone in which to interpret `timestamp`
462    pub fn add_year_months(
463        timestamp: <Self as ArrowPrimitiveType>::Native,
464        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
465        tz: Tz,
466    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
467        add_year_months::<Self>(timestamp, delta, tz)
468    }
469
470    /// Adds the given IntervalDayTimeType to an arrow TimestampSecondType.
471    ///
472    /// Returns `None` when it will result in overflow.
473    ///
474    /// # Arguments
475    ///
476    /// * `timestamp` - The date on which to perform the operation
477    /// * `delta` - The interval to add
478    /// * `tz` - The timezone in which to interpret `timestamp`
479    pub fn add_day_time(
480        timestamp: <Self as ArrowPrimitiveType>::Native,
481        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
482        tz: Tz,
483    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
484        add_day_time::<Self>(timestamp, delta, tz)
485    }
486
487    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampSecondType
488    ///
489    /// Returns `None` when it will result in overflow.
490    /// # Arguments
491    ///
492    /// * `timestamp` - The date on which to perform the operation
493    /// * `delta` - The interval to add
494    /// * `tz` - The timezone in which to interpret `timestamp`
495    pub fn add_month_day_nano(
496        timestamp: <Self as ArrowPrimitiveType>::Native,
497        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
498        tz: Tz,
499    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
500        add_month_day_nano::<Self>(timestamp, delta, tz)
501    }
502
503    /// Subtracts the given IntervalYearMonthType to an arrow TimestampSecondType
504    ///
505    /// Returns `None` when it will result in overflow.
506    ///
507    /// # Arguments
508    ///
509    /// * `timestamp` - The date on which to perform the operation
510    /// * `delta` - The interval to add
511    /// * `tz` - The timezone in which to interpret `timestamp`
512    pub fn subtract_year_months(
513        timestamp: <Self as ArrowPrimitiveType>::Native,
514        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
515        tz: Tz,
516    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
517        subtract_year_months::<Self>(timestamp, delta, tz)
518    }
519
520    /// Subtracts the given IntervalDayTimeType to an arrow TimestampSecondType
521    ///
522    /// Returns `None` when it will result in overflow.
523    ///
524    /// # Arguments
525    ///
526    /// * `timestamp` - The date on which to perform the operation
527    /// * `delta` - The interval to add
528    /// * `tz` - The timezone in which to interpret `timestamp`
529    pub fn subtract_day_time(
530        timestamp: <Self as ArrowPrimitiveType>::Native,
531        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
532        tz: Tz,
533    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
534        subtract_day_time::<Self>(timestamp, delta, tz)
535    }
536
537    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampSecondType
538    ///
539    /// Returns `None` when it will result in overflow.
540    ///
541    /// # Arguments
542    ///
543    /// * `timestamp` - The date on which to perform the operation
544    /// * `delta` - The interval to add
545    /// * `tz` - The timezone in which to interpret `timestamp`
546    pub fn subtract_month_day_nano(
547        timestamp: <Self as ArrowPrimitiveType>::Native,
548        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
549        tz: Tz,
550    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
551        subtract_month_day_nano::<Self>(timestamp, delta, tz)
552    }
553}
554
555impl TimestampMicrosecondType {
556    /// Adds the given IntervalYearMonthType to an arrow TimestampMicrosecondType
557    ///
558    /// # Arguments
559    ///
560    /// * `timestamp` - The date on which to perform the operation
561    /// * `delta` - The interval to add
562    /// * `tz` - The timezone in which to interpret `timestamp`
563    pub fn add_year_months(
564        timestamp: <Self as ArrowPrimitiveType>::Native,
565        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
566        tz: Tz,
567    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
568        add_year_months::<Self>(timestamp, delta, tz)
569    }
570
571    /// Adds the given IntervalDayTimeType to an arrow TimestampMicrosecondType
572    ///
573    /// # Arguments
574    ///
575    /// * `timestamp` - The date on which to perform the operation
576    /// * `delta` - The interval to add
577    /// * `tz` - The timezone in which to interpret `timestamp`
578    pub fn add_day_time(
579        timestamp: <Self as ArrowPrimitiveType>::Native,
580        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
581        tz: Tz,
582    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
583        add_day_time::<Self>(timestamp, delta, tz)
584    }
585
586    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampMicrosecondType
587    ///
588    /// # Arguments
589    ///
590    /// * `timestamp` - The date on which to perform the operation
591    /// * `delta` - The interval to add
592    /// * `tz` - The timezone in which to interpret `timestamp`
593    pub fn add_month_day_nano(
594        timestamp: <Self as ArrowPrimitiveType>::Native,
595        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
596        tz: Tz,
597    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
598        add_month_day_nano::<Self>(timestamp, delta, tz)
599    }
600
601    /// Subtracts the given IntervalYearMonthType to an arrow TimestampMicrosecondType
602    ///
603    /// # Arguments
604    ///
605    /// * `timestamp` - The date on which to perform the operation
606    /// * `delta` - The interval to add
607    /// * `tz` - The timezone in which to interpret `timestamp`
608    pub fn subtract_year_months(
609        timestamp: <Self as ArrowPrimitiveType>::Native,
610        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
611        tz: Tz,
612    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
613        subtract_year_months::<Self>(timestamp, delta, tz)
614    }
615
616    /// Subtracts the given IntervalDayTimeType to an arrow TimestampMicrosecondType
617    ///
618    /// # Arguments
619    ///
620    /// * `timestamp` - The date on which to perform the operation
621    /// * `delta` - The interval to add
622    /// * `tz` - The timezone in which to interpret `timestamp`
623    pub fn subtract_day_time(
624        timestamp: <Self as ArrowPrimitiveType>::Native,
625        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
626        tz: Tz,
627    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
628        subtract_day_time::<Self>(timestamp, delta, tz)
629    }
630
631    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampMicrosecondType
632    ///
633    /// # Arguments
634    ///
635    /// * `timestamp` - The date on which to perform the operation
636    /// * `delta` - The interval to add
637    /// * `tz` - The timezone in which to interpret `timestamp`
638    pub fn subtract_month_day_nano(
639        timestamp: <Self as ArrowPrimitiveType>::Native,
640        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
641        tz: Tz,
642    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
643        subtract_month_day_nano::<Self>(timestamp, delta, tz)
644    }
645}
646
647impl TimestampMillisecondType {
648    /// Adds the given IntervalYearMonthType to an arrow TimestampMillisecondType
649    ///
650    /// # Arguments
651    ///
652    /// * `timestamp` - The date on which to perform the operation
653    /// * `delta` - The interval to add
654    /// * `tz` - The timezone in which to interpret `timestamp`
655    pub fn add_year_months(
656        timestamp: <Self as ArrowPrimitiveType>::Native,
657        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
658        tz: Tz,
659    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
660        add_year_months::<Self>(timestamp, delta, tz)
661    }
662
663    /// Adds the given IntervalDayTimeType to an arrow TimestampMillisecondType
664    ///
665    /// # Arguments
666    ///
667    /// * `timestamp` - The date on which to perform the operation
668    /// * `delta` - The interval to add
669    /// * `tz` - The timezone in which to interpret `timestamp`
670    pub fn add_day_time(
671        timestamp: <Self as ArrowPrimitiveType>::Native,
672        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
673        tz: Tz,
674    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
675        add_day_time::<Self>(timestamp, delta, tz)
676    }
677
678    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampMillisecondType
679    ///
680    /// # Arguments
681    ///
682    /// * `timestamp` - The date on which to perform the operation
683    /// * `delta` - The interval to add
684    /// * `tz` - The timezone in which to interpret `timestamp`
685    pub fn add_month_day_nano(
686        timestamp: <Self as ArrowPrimitiveType>::Native,
687        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
688        tz: Tz,
689    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
690        add_month_day_nano::<Self>(timestamp, delta, tz)
691    }
692
693    /// Subtracts the given IntervalYearMonthType to an arrow TimestampMillisecondType
694    ///
695    /// # Arguments
696    ///
697    /// * `timestamp` - The date on which to perform the operation
698    /// * `delta` - The interval to add
699    /// * `tz` - The timezone in which to interpret `timestamp`
700    pub fn subtract_year_months(
701        timestamp: <Self as ArrowPrimitiveType>::Native,
702        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
703        tz: Tz,
704    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
705        subtract_year_months::<Self>(timestamp, delta, tz)
706    }
707
708    /// Subtracts the given IntervalDayTimeType to an arrow TimestampMillisecondType
709    ///
710    /// # Arguments
711    ///
712    /// * `timestamp` - The date on which to perform the operation
713    /// * `delta` - The interval to add
714    /// * `tz` - The timezone in which to interpret `timestamp`
715    pub fn subtract_day_time(
716        timestamp: <Self as ArrowPrimitiveType>::Native,
717        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
718        tz: Tz,
719    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
720        subtract_day_time::<Self>(timestamp, delta, tz)
721    }
722
723    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampMillisecondType
724    ///
725    /// # Arguments
726    ///
727    /// * `timestamp` - The date on which to perform the operation
728    /// * `delta` - The interval to add
729    /// * `tz` - The timezone in which to interpret `timestamp`
730    pub fn subtract_month_day_nano(
731        timestamp: <Self as ArrowPrimitiveType>::Native,
732        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
733        tz: Tz,
734    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
735        subtract_month_day_nano::<Self>(timestamp, delta, tz)
736    }
737}
738
739impl TimestampNanosecondType {
740    /// Adds the given IntervalYearMonthType to an arrow TimestampNanosecondType
741    ///
742    /// # Arguments
743    ///
744    /// * `timestamp` - The date on which to perform the operation
745    /// * `delta` - The interval to add
746    /// * `tz` - The timezone in which to interpret `timestamp`
747    pub fn add_year_months(
748        timestamp: <Self as ArrowPrimitiveType>::Native,
749        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
750        tz: Tz,
751    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
752        add_year_months::<Self>(timestamp, delta, tz)
753    }
754
755    /// Adds the given IntervalDayTimeType to an arrow TimestampNanosecondType
756    ///
757    /// # Arguments
758    ///
759    /// * `timestamp` - The date on which to perform the operation
760    /// * `delta` - The interval to add
761    /// * `tz` - The timezone in which to interpret `timestamp`
762    pub fn add_day_time(
763        timestamp: <Self as ArrowPrimitiveType>::Native,
764        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
765        tz: Tz,
766    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
767        add_day_time::<Self>(timestamp, delta, tz)
768    }
769
770    /// Adds the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType
771    ///
772    /// # Arguments
773    ///
774    /// * `timestamp` - The date on which to perform the operation
775    /// * `delta` - The interval to add
776    /// * `tz` - The timezone in which to interpret `timestamp`
777    pub fn add_month_day_nano(
778        timestamp: <Self as ArrowPrimitiveType>::Native,
779        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
780        tz: Tz,
781    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
782        add_month_day_nano::<Self>(timestamp, delta, tz)
783    }
784
785    /// Subtracts the given IntervalYearMonthType to an arrow TimestampNanosecondType
786    ///
787    /// # Arguments
788    ///
789    /// * `timestamp` - The date on which to perform the operation
790    /// * `delta` - The interval to add
791    /// * `tz` - The timezone in which to interpret `timestamp`
792    pub fn subtract_year_months(
793        timestamp: <Self as ArrowPrimitiveType>::Native,
794        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
795        tz: Tz,
796    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
797        subtract_year_months::<Self>(timestamp, delta, tz)
798    }
799
800    /// Subtracts the given IntervalDayTimeType to an arrow TimestampNanosecondType
801    ///
802    /// # Arguments
803    ///
804    /// * `timestamp` - The date on which to perform the operation
805    /// * `delta` - The interval to add
806    /// * `tz` - The timezone in which to interpret `timestamp`
807    pub fn subtract_day_time(
808        timestamp: <Self as ArrowPrimitiveType>::Native,
809        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
810        tz: Tz,
811    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
812        subtract_day_time::<Self>(timestamp, delta, tz)
813    }
814
815    /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType
816    ///
817    /// # Arguments
818    ///
819    /// * `timestamp` - The date on which to perform the operation
820    /// * `delta` - The interval to add
821    /// * `tz` - The timezone in which to interpret `timestamp`
822    pub fn subtract_month_day_nano(
823        timestamp: <Self as ArrowPrimitiveType>::Native,
824        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
825        tz: Tz,
826    ) -> Option<<Self as ArrowPrimitiveType>::Native> {
827        subtract_month_day_nano::<Self>(timestamp, delta, tz)
828    }
829}
830
831impl IntervalYearMonthType {
832    /// Creates a IntervalYearMonthType::Native
833    ///
834    /// # Arguments
835    ///
836    /// * `years` - The number of years (+/-) represented in this interval
837    /// * `months` - The number of months (+/-) represented in this interval
838    #[inline]
839    pub fn make_value(
840        years: i32,
841        months: i32,
842    ) -> <IntervalYearMonthType as ArrowPrimitiveType>::Native {
843        years * 12 + months
844    }
845
846    /// Turns a IntervalYearMonthType type into an i32 of months.
847    ///
848    /// This operation is technically a no-op, it is included for comprehensiveness.
849    ///
850    /// # Arguments
851    ///
852    /// * `i` - The IntervalYearMonthType::Native to convert
853    #[inline]
854    pub fn to_months(i: <IntervalYearMonthType as ArrowPrimitiveType>::Native) -> i32 {
855        i
856    }
857}
858
859impl IntervalDayTimeType {
860    /// Creates a IntervalDayTimeType::Native
861    ///
862    /// # Arguments
863    ///
864    /// * `days` - The number of days (+/-) represented in this interval
865    /// * `millis` - The number of milliseconds (+/-) represented in this interval
866    #[inline]
867    pub fn make_value(days: i32, milliseconds: i32) -> IntervalDayTime {
868        IntervalDayTime { days, milliseconds }
869    }
870
871    /// Turns a IntervalDayTimeType into a tuple of (days, milliseconds)
872    ///
873    /// # Arguments
874    ///
875    /// * `i` - The IntervalDayTimeType to convert
876    #[inline]
877    pub fn to_parts(i: IntervalDayTime) -> (i32, i32) {
878        (i.days, i.milliseconds)
879    }
880}
881
882impl IntervalMonthDayNanoType {
883    /// Creates a IntervalMonthDayNanoType::Native
884    ///
885    /// # Arguments
886    ///
887    /// * `months` - The number of months (+/-) represented in this interval
888    /// * `days` - The number of days (+/-) represented in this interval
889    /// * `nanos` - The number of nanoseconds (+/-) represented in this interval
890    #[inline]
891    pub fn make_value(months: i32, days: i32, nanoseconds: i64) -> IntervalMonthDayNano {
892        IntervalMonthDayNano {
893            months,
894            days,
895            nanoseconds,
896        }
897    }
898
899    /// Turns a IntervalMonthDayNanoType into a tuple of (months, days, nanos)
900    ///
901    /// # Arguments
902    ///
903    /// * `i` - The IntervalMonthDayNanoType to convert
904    #[inline]
905    pub fn to_parts(i: IntervalMonthDayNano) -> (i32, i32, i64) {
906        (i.months, i.days, i.nanoseconds)
907    }
908}
909
910impl Date32Type {
911    /// Converts an arrow Date32Type into a chrono::NaiveDate
912    ///
913    /// # Arguments
914    ///
915    /// * `i` - The Date32Type to convert
916    pub fn to_naive_date(i: <Date32Type as ArrowPrimitiveType>::Native) -> NaiveDate {
917        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
918        epoch.add(Duration::try_days(i as i64).unwrap())
919    }
920
921    /// Converts a chrono::NaiveDate into an arrow Date32Type
922    ///
923    /// # Arguments
924    ///
925    /// * `d` - The NaiveDate to convert
926    pub fn from_naive_date(d: NaiveDate) -> <Date32Type as ArrowPrimitiveType>::Native {
927        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
928        d.sub(epoch).num_days() as <Date32Type as ArrowPrimitiveType>::Native
929    }
930
931    /// Adds the given IntervalYearMonthType to an arrow Date32Type
932    ///
933    /// # Arguments
934    ///
935    /// * `date` - The date on which to perform the operation
936    /// * `delta` - The interval to add
937    pub fn add_year_months(
938        date: <Date32Type as ArrowPrimitiveType>::Native,
939        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
940    ) -> <Date32Type as ArrowPrimitiveType>::Native {
941        let prior = Date32Type::to_naive_date(date);
942        let months = IntervalYearMonthType::to_months(delta);
943        let posterior = shift_months(prior, months);
944        Date32Type::from_naive_date(posterior)
945    }
946
947    /// Adds the given IntervalDayTimeType to an arrow Date32Type
948    ///
949    /// # Arguments
950    ///
951    /// * `date` - The date on which to perform the operation
952    /// * `delta` - The interval to add
953    pub fn add_day_time(
954        date: <Date32Type as ArrowPrimitiveType>::Native,
955        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
956    ) -> <Date32Type as ArrowPrimitiveType>::Native {
957        let (days, ms) = IntervalDayTimeType::to_parts(delta);
958        let res = Date32Type::to_naive_date(date);
959        let res = res.add(Duration::try_days(days as i64).unwrap());
960        let res = res.add(Duration::try_milliseconds(ms as i64).unwrap());
961        Date32Type::from_naive_date(res)
962    }
963
964    /// Adds the given IntervalMonthDayNanoType to an arrow Date32Type
965    ///
966    /// # Arguments
967    ///
968    /// * `date` - The date on which to perform the operation
969    /// * `delta` - The interval to add
970    pub fn add_month_day_nano(
971        date: <Date32Type as ArrowPrimitiveType>::Native,
972        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
973    ) -> <Date32Type as ArrowPrimitiveType>::Native {
974        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
975        let res = Date32Type::to_naive_date(date);
976        let res = shift_months(res, months);
977        let res = res.add(Duration::try_days(days as i64).unwrap());
978        let res = res.add(Duration::nanoseconds(nanos));
979        Date32Type::from_naive_date(res)
980    }
981
982    /// Subtract the given IntervalYearMonthType to an arrow Date32Type
983    ///
984    /// # Arguments
985    ///
986    /// * `date` - The date on which to perform the operation
987    /// * `delta` - The interval to subtract
988    pub fn subtract_year_months(
989        date: <Date32Type as ArrowPrimitiveType>::Native,
990        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
991    ) -> <Date32Type as ArrowPrimitiveType>::Native {
992        let prior = Date32Type::to_naive_date(date);
993        let months = IntervalYearMonthType::to_months(-delta);
994        let posterior = shift_months(prior, months);
995        Date32Type::from_naive_date(posterior)
996    }
997
998    /// Subtract the given IntervalDayTimeType to an arrow Date32Type
999    ///
1000    /// # Arguments
1001    ///
1002    /// * `date` - The date on which to perform the operation
1003    /// * `delta` - The interval to subtract
1004    pub fn subtract_day_time(
1005        date: <Date32Type as ArrowPrimitiveType>::Native,
1006        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1007    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1008        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1009        let res = Date32Type::to_naive_date(date);
1010        let res = res.sub(Duration::try_days(days as i64).unwrap());
1011        let res = res.sub(Duration::try_milliseconds(ms as i64).unwrap());
1012        Date32Type::from_naive_date(res)
1013    }
1014
1015    /// Subtract the given IntervalMonthDayNanoType to an arrow Date32Type
1016    ///
1017    /// # Arguments
1018    ///
1019    /// * `date` - The date on which to perform the operation
1020    /// * `delta` - The interval to subtract
1021    pub fn subtract_month_day_nano(
1022        date: <Date32Type as ArrowPrimitiveType>::Native,
1023        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1024    ) -> <Date32Type as ArrowPrimitiveType>::Native {
1025        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1026        let res = Date32Type::to_naive_date(date);
1027        let res = shift_months(res, -months);
1028        let res = res.sub(Duration::try_days(days as i64).unwrap());
1029        let res = res.sub(Duration::nanoseconds(nanos));
1030        Date32Type::from_naive_date(res)
1031    }
1032}
1033
1034impl Date64Type {
1035    /// Converts an arrow Date64Type into a chrono::NaiveDate
1036    ///
1037    /// # Arguments
1038    ///
1039    /// * `i` - The Date64Type to convert
1040    pub fn to_naive_date(i: <Date64Type as ArrowPrimitiveType>::Native) -> NaiveDate {
1041        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1042        epoch.add(Duration::try_milliseconds(i).unwrap())
1043    }
1044
1045    /// Converts a chrono::NaiveDate into an arrow Date64Type
1046    ///
1047    /// # Arguments
1048    ///
1049    /// * `d` - The NaiveDate to convert
1050    pub fn from_naive_date(d: NaiveDate) -> <Date64Type as ArrowPrimitiveType>::Native {
1051        let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1052        d.sub(epoch).num_milliseconds() as <Date64Type as ArrowPrimitiveType>::Native
1053    }
1054
1055    /// Adds the given IntervalYearMonthType to an arrow Date64Type
1056    ///
1057    /// # Arguments
1058    ///
1059    /// * `date` - The date on which to perform the operation
1060    /// * `delta` - The interval to add
1061    pub fn add_year_months(
1062        date: <Date64Type as ArrowPrimitiveType>::Native,
1063        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1064    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1065        let prior = Date64Type::to_naive_date(date);
1066        let months = IntervalYearMonthType::to_months(delta);
1067        let posterior = shift_months(prior, months);
1068        Date64Type::from_naive_date(posterior)
1069    }
1070
1071    /// Adds the given IntervalDayTimeType to an arrow Date64Type
1072    ///
1073    /// # Arguments
1074    ///
1075    /// * `date` - The date on which to perform the operation
1076    /// * `delta` - The interval to add
1077    pub fn add_day_time(
1078        date: <Date64Type as ArrowPrimitiveType>::Native,
1079        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1080    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1081        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1082        let res = Date64Type::to_naive_date(date);
1083        let res = res.add(Duration::try_days(days as i64).unwrap());
1084        let res = res.add(Duration::try_milliseconds(ms as i64).unwrap());
1085        Date64Type::from_naive_date(res)
1086    }
1087
1088    /// Adds the given IntervalMonthDayNanoType to an arrow Date64Type
1089    ///
1090    /// # Arguments
1091    ///
1092    /// * `date` - The date on which to perform the operation
1093    /// * `delta` - The interval to add
1094    pub fn add_month_day_nano(
1095        date: <Date64Type as ArrowPrimitiveType>::Native,
1096        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1097    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1098        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1099        let res = Date64Type::to_naive_date(date);
1100        let res = shift_months(res, months);
1101        let res = res.add(Duration::try_days(days as i64).unwrap());
1102        let res = res.add(Duration::nanoseconds(nanos));
1103        Date64Type::from_naive_date(res)
1104    }
1105
1106    /// Subtract the given IntervalYearMonthType to an arrow Date64Type
1107    ///
1108    /// # Arguments
1109    ///
1110    /// * `date` - The date on which to perform the operation
1111    /// * `delta` - The interval to subtract
1112    pub fn subtract_year_months(
1113        date: <Date64Type as ArrowPrimitiveType>::Native,
1114        delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
1115    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1116        let prior = Date64Type::to_naive_date(date);
1117        let months = IntervalYearMonthType::to_months(-delta);
1118        let posterior = shift_months(prior, months);
1119        Date64Type::from_naive_date(posterior)
1120    }
1121
1122    /// Subtract the given IntervalDayTimeType to an arrow Date64Type
1123    ///
1124    /// # Arguments
1125    ///
1126    /// * `date` - The date on which to perform the operation
1127    /// * `delta` - The interval to subtract
1128    pub fn subtract_day_time(
1129        date: <Date64Type as ArrowPrimitiveType>::Native,
1130        delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native,
1131    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1132        let (days, ms) = IntervalDayTimeType::to_parts(delta);
1133        let res = Date64Type::to_naive_date(date);
1134        let res = res.sub(Duration::try_days(days as i64).unwrap());
1135        let res = res.sub(Duration::try_milliseconds(ms as i64).unwrap());
1136        Date64Type::from_naive_date(res)
1137    }
1138
1139    /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type
1140    ///
1141    /// # Arguments
1142    ///
1143    /// * `date` - The date on which to perform the operation
1144    /// * `delta` - The interval to subtract
1145    pub fn subtract_month_day_nano(
1146        date: <Date64Type as ArrowPrimitiveType>::Native,
1147        delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native,
1148    ) -> <Date64Type as ArrowPrimitiveType>::Native {
1149        let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta);
1150        let res = Date64Type::to_naive_date(date);
1151        let res = shift_months(res, -months);
1152        let res = res.sub(Duration::try_days(days as i64).unwrap());
1153        let res = res.sub(Duration::nanoseconds(nanos));
1154        Date64Type::from_naive_date(res)
1155    }
1156}
1157
1158/// Crate private types for Decimal Arrays
1159///
1160/// Not intended to be used outside this crate
1161mod decimal {
1162    use super::*;
1163
1164    pub trait DecimalTypeSealed {}
1165    impl DecimalTypeSealed for Decimal128Type {}
1166    impl DecimalTypeSealed for Decimal256Type {}
1167}
1168
1169/// A trait over the decimal types, used by [`PrimitiveArray`] to provide a generic
1170/// implementation across the various decimal types
1171///
1172/// Implemented by [`Decimal128Type`] and [`Decimal256Type`] for [`Decimal128Array`]
1173/// and [`Decimal256Array`] respectively
1174///
1175/// [`PrimitiveArray`]: crate::array::PrimitiveArray
1176/// [`Decimal128Array`]: crate::array::Decimal128Array
1177/// [`Decimal256Array`]: crate::array::Decimal256Array
1178pub trait DecimalType:
1179    'static + Send + Sync + ArrowPrimitiveType + decimal::DecimalTypeSealed
1180{
1181    /// Width of the type
1182    const BYTE_LENGTH: usize;
1183    /// Maximum number of significant digits
1184    const MAX_PRECISION: u8;
1185    /// Maximum no of digits after the decimal point (note the scale can be negative)
1186    const MAX_SCALE: i8;
1187    /// fn to create its [`DataType`]
1188    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType;
1189    /// Default values for [`DataType`]
1190    const DEFAULT_TYPE: DataType;
1191
1192    /// "Decimal128" or "Decimal256", for use in error messages
1193    const PREFIX: &'static str;
1194
1195    /// Formats the decimal value with the provided precision and scale
1196    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String;
1197
1198    /// Validates that `value` contains no more than `precision` decimal digits
1199    fn validate_decimal_precision(value: Self::Native, precision: u8) -> Result<(), ArrowError>;
1200
1201    /// Determines whether `value` contains no more than `precision` decimal digits
1202    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool;
1203}
1204
1205/// Validate that `precision` and `scale` are valid for `T`
1206///
1207/// Returns an Error if:
1208/// - `precision` is zero
1209/// - `precision` is larger than `T:MAX_PRECISION`
1210/// - `scale` is larger than `T::MAX_SCALE`
1211/// - `scale` is > `precision`
1212pub fn validate_decimal_precision_and_scale<T: DecimalType>(
1213    precision: u8,
1214    scale: i8,
1215) -> Result<(), ArrowError> {
1216    if precision == 0 {
1217        return Err(ArrowError::InvalidArgumentError(format!(
1218            "precision cannot be 0, has to be between [1, {}]",
1219            T::MAX_PRECISION
1220        )));
1221    }
1222    if precision > T::MAX_PRECISION {
1223        return Err(ArrowError::InvalidArgumentError(format!(
1224            "precision {} is greater than max {}",
1225            precision,
1226            T::MAX_PRECISION
1227        )));
1228    }
1229    if scale > T::MAX_SCALE {
1230        return Err(ArrowError::InvalidArgumentError(format!(
1231            "scale {} is greater than max {}",
1232            scale,
1233            T::MAX_SCALE
1234        )));
1235    }
1236    if scale > 0 && scale as u8 > precision {
1237        return Err(ArrowError::InvalidArgumentError(format!(
1238            "scale {scale} is greater than precision {precision}"
1239        )));
1240    }
1241
1242    Ok(())
1243}
1244
1245/// The decimal type for a Decimal128Array
1246#[derive(Debug)]
1247pub struct Decimal128Type {}
1248
1249impl DecimalType for Decimal128Type {
1250    const BYTE_LENGTH: usize = 16;
1251    const MAX_PRECISION: u8 = DECIMAL128_MAX_PRECISION;
1252    const MAX_SCALE: i8 = DECIMAL128_MAX_SCALE;
1253    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal128;
1254    const DEFAULT_TYPE: DataType =
1255        DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1256    const PREFIX: &'static str = "Decimal128";
1257
1258    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1259        format_decimal_str(&value.to_string(), precision as usize, scale)
1260    }
1261
1262    fn validate_decimal_precision(num: i128, precision: u8) -> Result<(), ArrowError> {
1263        validate_decimal_precision(num, precision)
1264    }
1265
1266    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1267        is_validate_decimal_precision(value, precision)
1268    }
1269}
1270
1271impl ArrowPrimitiveType for Decimal128Type {
1272    type Native = i128;
1273
1274    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1275}
1276
1277impl primitive::PrimitiveTypeSealed for Decimal128Type {}
1278
1279/// The decimal type for a Decimal256Array
1280#[derive(Debug)]
1281pub struct Decimal256Type {}
1282
1283impl DecimalType for Decimal256Type {
1284    const BYTE_LENGTH: usize = 32;
1285    const MAX_PRECISION: u8 = DECIMAL256_MAX_PRECISION;
1286    const MAX_SCALE: i8 = DECIMAL256_MAX_SCALE;
1287    const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal256;
1288    const DEFAULT_TYPE: DataType =
1289        DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE);
1290    const PREFIX: &'static str = "Decimal256";
1291
1292    fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String {
1293        format_decimal_str(&value.to_string(), precision as usize, scale)
1294    }
1295
1296    fn validate_decimal_precision(num: i256, precision: u8) -> Result<(), ArrowError> {
1297        validate_decimal256_precision(num, precision)
1298    }
1299
1300    fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool {
1301        is_validate_decimal256_precision(value, precision)
1302    }
1303}
1304
1305impl ArrowPrimitiveType for Decimal256Type {
1306    type Native = i256;
1307
1308    const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE;
1309}
1310
1311impl primitive::PrimitiveTypeSealed for Decimal256Type {}
1312
1313fn format_decimal_str(value_str: &str, precision: usize, scale: i8) -> String {
1314    let (sign, rest) = match value_str.strip_prefix('-') {
1315        Some(stripped) => ("-", stripped),
1316        None => ("", value_str),
1317    };
1318    let bound = precision.min(rest.len()) + sign.len();
1319    let value_str = &value_str[0..bound];
1320
1321    if scale == 0 {
1322        value_str.to_string()
1323    } else if scale < 0 {
1324        let padding = value_str.len() + scale.unsigned_abs() as usize;
1325        format!("{value_str:0<padding$}")
1326    } else if rest.len() > scale as usize {
1327        // Decimal separator is in the middle of the string
1328        let (whole, decimal) = value_str.split_at(value_str.len() - scale as usize);
1329        format!("{whole}.{decimal}")
1330    } else {
1331        // String has to be padded
1332        format!("{}0.{:0>width$}", sign, rest, width = scale as usize)
1333    }
1334}
1335
1336/// Crate private types for Byte Arrays
1337///
1338/// Not intended to be used outside this crate
1339pub(crate) mod bytes {
1340    use super::*;
1341
1342    pub trait ByteArrayTypeSealed {}
1343    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericStringType<O> {}
1344    impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericBinaryType<O> {}
1345
1346    pub trait ByteArrayNativeType: std::fmt::Debug + Send + Sync {
1347        fn from_bytes_checked(b: &[u8]) -> Option<&Self>;
1348
1349        /// # Safety
1350        ///
1351        /// `b` must be a valid byte sequence for `Self`
1352        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self;
1353    }
1354
1355    impl ByteArrayNativeType for [u8] {
1356        #[inline]
1357        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1358            Some(b)
1359        }
1360
1361        #[inline]
1362        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1363            b
1364        }
1365    }
1366
1367    impl ByteArrayNativeType for str {
1368        #[inline]
1369        fn from_bytes_checked(b: &[u8]) -> Option<&Self> {
1370            std::str::from_utf8(b).ok()
1371        }
1372
1373        #[inline]
1374        unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self {
1375            std::str::from_utf8_unchecked(b)
1376        }
1377    }
1378}
1379
1380/// A trait over the variable-size byte array types
1381///
1382/// See [Variable Size Binary Layout](https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout)
1383pub trait ByteArrayType: 'static + Send + Sync + bytes::ByteArrayTypeSealed {
1384    /// Type of offset i.e i32/i64
1385    type Offset: OffsetSizeTrait;
1386    /// Type for representing its equivalent rust type i.e
1387    /// Utf8Array will have native type has &str
1388    /// BinaryArray will have type as [u8]
1389    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1390
1391    /// "Binary" or "String", for use in error messages
1392    const PREFIX: &'static str;
1393
1394    /// Datatype of array elements
1395    const DATA_TYPE: DataType;
1396
1397    /// Verifies that every consecutive pair of `offsets` denotes a valid slice of `values`
1398    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError>;
1399}
1400
1401/// [`ByteArrayType`] for string arrays
1402pub struct GenericStringType<O: OffsetSizeTrait> {
1403    phantom: PhantomData<O>,
1404}
1405
1406impl<O: OffsetSizeTrait> ByteArrayType for GenericStringType<O> {
1407    type Offset = O;
1408    type Native = str;
1409    const PREFIX: &'static str = "String";
1410
1411    const DATA_TYPE: DataType = if O::IS_LARGE {
1412        DataType::LargeUtf8
1413    } else {
1414        DataType::Utf8
1415    };
1416
1417    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1418        // Verify that the slice as a whole is valid UTF-8
1419        let validated = std::str::from_utf8(values).map_err(|e| {
1420            ArrowError::InvalidArgumentError(format!("Encountered non UTF-8 data: {e}"))
1421        })?;
1422
1423        // Verify each offset is at a valid character boundary in this UTF-8 array
1424        for offset in offsets.iter() {
1425            let o = offset.as_usize();
1426            if !validated.is_char_boundary(o) {
1427                if o < validated.len() {
1428                    return Err(ArrowError::InvalidArgumentError(format!(
1429                        "Split UTF-8 codepoint at offset {o}"
1430                    )));
1431                }
1432                return Err(ArrowError::InvalidArgumentError(format!(
1433                    "Offset of {o} exceeds length of values {}",
1434                    validated.len()
1435                )));
1436            }
1437        }
1438        Ok(())
1439    }
1440}
1441
1442/// An arrow utf8 array with i32 offsets
1443pub type Utf8Type = GenericStringType<i32>;
1444/// An arrow utf8 array with i64 offsets
1445pub type LargeUtf8Type = GenericStringType<i64>;
1446
1447/// [`ByteArrayType`] for binary arrays
1448pub struct GenericBinaryType<O: OffsetSizeTrait> {
1449    phantom: PhantomData<O>,
1450}
1451
1452impl<O: OffsetSizeTrait> ByteArrayType for GenericBinaryType<O> {
1453    type Offset = O;
1454    type Native = [u8];
1455    const PREFIX: &'static str = "Binary";
1456
1457    const DATA_TYPE: DataType = if O::IS_LARGE {
1458        DataType::LargeBinary
1459    } else {
1460        DataType::Binary
1461    };
1462
1463    fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> {
1464        // offsets are guaranteed to be monotonically increasing and non-empty
1465        let max_offset = offsets.last().unwrap().as_usize();
1466        if values.len() < max_offset {
1467            return Err(ArrowError::InvalidArgumentError(format!(
1468                "Maximum offset of {max_offset} is larger than values of length {}",
1469                values.len()
1470            )));
1471        }
1472        Ok(())
1473    }
1474}
1475
1476/// An arrow binary array with i32 offsets
1477pub type BinaryType = GenericBinaryType<i32>;
1478/// An arrow binary array with i64 offsets
1479pub type LargeBinaryType = GenericBinaryType<i64>;
1480
1481mod byte_view {
1482    use crate::types::{BinaryViewType, StringViewType};
1483
1484    pub trait Sealed: Send + Sync {}
1485    impl Sealed for StringViewType {}
1486    impl Sealed for BinaryViewType {}
1487}
1488
1489/// A trait over the variable length bytes view array types
1490pub trait ByteViewType: byte_view::Sealed + 'static + PartialEq + Send + Sync {
1491    /// If element in array is utf8 encoded string.
1492    const IS_UTF8: bool;
1493
1494    /// Datatype of array elements
1495    const DATA_TYPE: DataType = if Self::IS_UTF8 {
1496        DataType::Utf8View
1497    } else {
1498        DataType::BinaryView
1499    };
1500
1501    /// "Binary" or "String", for use in displayed or error messages
1502    const PREFIX: &'static str;
1503
1504    /// Type for representing its equivalent rust type i.e
1505    /// Utf8Array will have native type has &str
1506    /// BinaryArray will have type as [u8]
1507    type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized;
1508
1509    /// Type for owned corresponding to `Native`
1510    type Owned: Debug + Clone + Sync + Send + AsRef<Self::Native>;
1511
1512    /// Verifies that the provided buffers are valid for this array type
1513    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError>;
1514}
1515
1516/// [`ByteViewType`] for string arrays
1517#[derive(PartialEq)]
1518pub struct StringViewType {}
1519
1520impl ByteViewType for StringViewType {
1521    const IS_UTF8: bool = true;
1522    const PREFIX: &'static str = "String";
1523
1524    type Native = str;
1525    type Owned = String;
1526
1527    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1528        validate_string_view(views, buffers)
1529    }
1530}
1531
1532/// [`BinaryViewType`] for string arrays
1533#[derive(PartialEq)]
1534pub struct BinaryViewType {}
1535
1536impl ByteViewType for BinaryViewType {
1537    const IS_UTF8: bool = false;
1538    const PREFIX: &'static str = "Binary";
1539    type Native = [u8];
1540    type Owned = Vec<u8>;
1541
1542    fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> {
1543        validate_binary_view(views, buffers)
1544    }
1545}
1546
1547#[cfg(test)]
1548mod tests {
1549    use super::*;
1550    use arrow_data::{layout, BufferSpec};
1551
1552    #[test]
1553    fn month_day_nano_should_roundtrip() {
1554        let value = IntervalMonthDayNanoType::make_value(1, 2, 3);
1555        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (1, 2, 3));
1556    }
1557
1558    #[test]
1559    fn month_day_nano_should_roundtrip_neg() {
1560        let value = IntervalMonthDayNanoType::make_value(-1, -2, -3);
1561        assert_eq!(IntervalMonthDayNanoType::to_parts(value), (-1, -2, -3));
1562    }
1563
1564    #[test]
1565    fn day_time_should_roundtrip() {
1566        let value = IntervalDayTimeType::make_value(1, 2);
1567        assert_eq!(IntervalDayTimeType::to_parts(value), (1, 2));
1568    }
1569
1570    #[test]
1571    fn day_time_should_roundtrip_neg() {
1572        let value = IntervalDayTimeType::make_value(-1, -2);
1573        assert_eq!(IntervalDayTimeType::to_parts(value), (-1, -2));
1574    }
1575
1576    #[test]
1577    fn year_month_should_roundtrip() {
1578        let value = IntervalYearMonthType::make_value(1, 2);
1579        assert_eq!(IntervalYearMonthType::to_months(value), 14);
1580    }
1581
1582    #[test]
1583    fn year_month_should_roundtrip_neg() {
1584        let value = IntervalYearMonthType::make_value(-1, -2);
1585        assert_eq!(IntervalYearMonthType::to_months(value), -14);
1586    }
1587
1588    fn test_layout<T: ArrowPrimitiveType>() {
1589        let layout = layout(&T::DATA_TYPE);
1590
1591        assert_eq!(layout.buffers.len(), 1);
1592
1593        let spec = &layout.buffers[0];
1594        assert_eq!(
1595            spec,
1596            &BufferSpec::FixedWidth {
1597                byte_width: std::mem::size_of::<T::Native>(),
1598                alignment: std::mem::align_of::<T::Native>(),
1599            }
1600        );
1601    }
1602
1603    #[test]
1604    fn test_layouts() {
1605        test_layout::<Int8Type>();
1606        test_layout::<Int16Type>();
1607        test_layout::<Int32Type>();
1608        test_layout::<Int64Type>();
1609        test_layout::<UInt8Type>();
1610        test_layout::<UInt16Type>();
1611        test_layout::<UInt32Type>();
1612        test_layout::<UInt64Type>();
1613        test_layout::<Float16Type>();
1614        test_layout::<Float32Type>();
1615        test_layout::<Float64Type>();
1616        test_layout::<Decimal128Type>();
1617        test_layout::<Decimal256Type>();
1618        test_layout::<TimestampNanosecondType>();
1619        test_layout::<TimestampMillisecondType>();
1620        test_layout::<TimestampMicrosecondType>();
1621        test_layout::<TimestampNanosecondType>();
1622        test_layout::<TimestampSecondType>();
1623        test_layout::<Date32Type>();
1624        test_layout::<Date64Type>();
1625        test_layout::<Time32SecondType>();
1626        test_layout::<Time32MillisecondType>();
1627        test_layout::<Time64MicrosecondType>();
1628        test_layout::<Time64NanosecondType>();
1629        test_layout::<IntervalMonthDayNanoType>();
1630        test_layout::<IntervalDayTimeType>();
1631        test_layout::<IntervalYearMonthType>();
1632        test_layout::<DurationNanosecondType>();
1633        test_layout::<DurationMicrosecondType>();
1634        test_layout::<DurationMillisecondType>();
1635        test_layout::<DurationSecondType>();
1636    }
1637}