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 phys: ChunkedArray<Physical>,
39    pub dtype: DataType,
40    _phantom: PhantomData<Logical>,
41}
42
43impl<K: PolarsDataType, T: PolarsDataType> Clone for Logical<K, T> {
44    fn clone(&self) -> Self {
45        Self {
46            phys: self.phys.clone(),
47            dtype: self.dtype.clone(),
48            _phantom: PhantomData,
49        }
50    }
51}
52
53impl<K: PolarsDataType, T: PolarsDataType> Deref for Logical<K, T> {
54    type Target = ChunkedArray<T>;
55
56    fn deref(&self) -> &Self::Target {
57        &self.phys
58    }
59}
60
61impl<K: PolarsDataType, T: PolarsDataType> DerefMut for Logical<K, T> {
62    fn deref_mut(&mut self) -> &mut Self::Target {
63        &mut self.phys
64    }
65}
66
67impl<K: PolarsDataType, T: PolarsDataType> Logical<K, T> {
68    pub fn new_logical(phys: ChunkedArray<T>, dtype: DataType) -> Logical<K, T> {
69        Logical {
70            phys,
71            dtype,
72            _phantom: PhantomData,
73        }
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.phys
105    }
106    pub fn field(&self) -> Field {
107        let name = self.phys.ref_field().name();
108        Field::new(name.clone(), LogicalType::dtype(self).clone())
109    }
110}