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