polars_core/chunked_array/logical/
mod.rs

1#[cfg(feature = "dtype-date")]
2mod date;
3#[cfg(feature = "dtype-date")]
4pub use date::*;
5#[cfg(feature = "dtype-datetime")]
6mod datetime;
7#[cfg(feature = "dtype-datetime")]
8pub use datetime::*;
9#[cfg(feature = "dtype-decimal")]
10mod decimal;
11#[cfg(feature = "dtype-decimal")]
12pub use decimal::*;
13#[cfg(feature = "dtype-duration")]
14mod duration;
15#[cfg(feature = "dtype-duration")]
16pub use duration::*;
17#[cfg(feature = "dtype-categorical")]
18pub mod categorical;
19#[cfg(feature = "dtype-categorical")]
20pub mod enum_;
21#[cfg(feature = "dtype-time")]
22mod time;
23
24use std::marker::PhantomData;
25use std::ops::{Deref, DerefMut};
26
27#[cfg(feature = "dtype-categorical")]
28pub use categorical::*;
29#[cfg(feature = "dtype-time")]
30pub use time::*;
31
32use crate::chunked_array::cast::CastOptions;
33use crate::prelude::*;
34
35/// Maps a logical type to a chunked array implementation of the physical type.
36/// This saves a lot of compiler bloat and allows us to reuse functionality.
37pub struct Logical<Logical: PolarsDataType, Physical: PolarsDataType>(
38    pub ChunkedArray<Physical>,
39    PhantomData<Logical>,
40    pub Option<DataType>,
41);
42
43impl<K: PolarsDataType, T: PolarsDataType> Default for Logical<K, T> {
44    fn default() -> Self {
45        Self(Default::default(), Default::default(), Default::default())
46    }
47}
48
49impl<K: PolarsDataType, T: PolarsDataType> Clone for Logical<K, T> {
50    fn clone(&self) -> Self {
51        let mut new = Logical::<K, _>::new_logical(self.0.clone());
52        new.2.clone_from(&self.2);
53        new
54    }
55}
56
57impl<K: PolarsDataType, T: PolarsDataType> Deref for Logical<K, T> {
58    type Target = ChunkedArray<T>;
59
60    fn deref(&self) -> &Self::Target {
61        &self.0
62    }
63}
64
65impl<K: PolarsDataType, T: PolarsDataType> DerefMut for Logical<K, T> {
66    fn deref_mut(&mut self) -> &mut Self::Target {
67        &mut self.0
68    }
69}
70
71impl<K: PolarsDataType, T: PolarsDataType> Logical<K, T> {
72    pub fn new_logical<J: PolarsDataType>(ca: ChunkedArray<T>) -> Logical<J, T> {
73        Logical(ca, PhantomData, None)
74    }
75}
76
77pub trait LogicalType {
78    /// Get data type of [`ChunkedArray`].
79    fn dtype(&self) -> &DataType;
80
81    /// Gets [`AnyValue`] from [`LogicalType`]
82    fn get_any_value(&self, _i: usize) -> PolarsResult<AnyValue<'_>> {
83        unimplemented!()
84    }
85
86    /// # Safety
87    /// Does not do any bound checks.
88    unsafe fn get_any_value_unchecked(&self, _i: usize) -> AnyValue<'_> {
89        unimplemented!()
90    }
91
92    fn cast_with_options(&self, dtype: &DataType, options: CastOptions) -> PolarsResult<Series>;
93
94    fn cast(&self, dtype: &DataType) -> PolarsResult<Series> {
95        self.cast_with_options(dtype, CastOptions::NonStrict)
96    }
97}
98
99impl<K: PolarsDataType, T: PolarsDataType> Logical<K, T>
100where
101    Self: LogicalType,
102{
103    pub fn physical(&self) -> &ChunkedArray<T> {
104        &self.0
105    }
106    pub fn field(&self) -> Field {
107        let name = self.0.ref_field().name();
108        Field::new(name.clone(), LogicalType::dtype(self).clone())
109    }
110}