polars_core/chunked_array/logical/
mod.rs1#[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-time")]
20mod time;
21
22use std::marker::PhantomData;
23
24#[cfg(feature = "dtype-categorical")]
25pub use categorical::*;
26#[cfg(feature = "dtype-time")]
27pub use time::*;
28
29use crate::chunked_array::cast::CastOptions;
30use crate::prelude::*;
31
32pub struct Logical<Logical: PolarsDataType, Physical: PolarsDataType> {
35 pub phys: ChunkedArray<Physical>,
36 pub dtype: DataType,
37 _phantom: PhantomData<Logical>,
38}
39
40impl<K: PolarsDataType, T: PolarsDataType> Clone for Logical<K, T> {
41 fn clone(&self) -> Self {
42 Self {
43 phys: self.phys.clone(),
44 dtype: self.dtype.clone(),
45 _phantom: PhantomData,
46 }
47 }
48}
49
50impl<K: PolarsDataType, T: PolarsDataType> Logical<K, T> {
51 pub unsafe fn new_logical(phys: ChunkedArray<T>, dtype: DataType) -> Logical<K, T> {
54 Logical {
55 phys,
56 dtype,
57 _phantom: PhantomData,
58 }
59 }
60}
61
62pub trait LogicalType {
63 fn dtype(&self) -> &DataType;
65
66 fn get_any_value(&self, _i: usize) -> PolarsResult<AnyValue<'_>> {
68 unimplemented!()
69 }
70
71 unsafe fn get_any_value_unchecked(&self, _i: usize) -> AnyValue<'_> {
74 unimplemented!()
75 }
76
77 fn cast_with_options(&self, dtype: &DataType, options: CastOptions) -> PolarsResult<Series>;
78
79 fn cast(&self, dtype: &DataType) -> PolarsResult<Series> {
80 self.cast_with_options(dtype, CastOptions::NonStrict)
81 }
82}
83
84impl<K: PolarsDataType, T: PolarsDataType> Logical<K, T>
85where
86 Self: LogicalType,
87{
88 #[inline(always)]
89 pub fn name(&self) -> &PlSmallStr {
90 self.phys.name()
91 }
92
93 #[inline(always)]
94 pub fn rename(&mut self, name: PlSmallStr) {
95 self.phys.rename(name)
96 }
97
98 #[inline(always)]
99 pub fn len(&self) -> usize {
100 self.phys.len()
101 }
102
103 #[inline(always)]
104 pub fn is_empty(&self) -> bool {
105 self.len() == 0
106 }
107
108 #[inline(always)]
109 pub fn null_count(&self) -> usize {
110 self.phys.null_count()
111 }
112
113 #[inline(always)]
114 pub fn has_nulls(&self) -> bool {
115 self.phys.has_nulls()
116 }
117
118 #[inline(always)]
119 pub fn is_null(&self) -> BooleanChunked {
120 self.phys.is_null()
121 }
122
123 #[inline(always)]
124 pub fn is_not_null(&self) -> BooleanChunked {
125 self.phys.is_not_null()
126 }
127
128 #[inline(always)]
129 pub fn split_at(&self, offset: i64) -> (Self, Self) {
130 let (left, right) = self.phys.split_at(offset);
131 unsafe {
132 (
133 Self::new_logical(left, self.dtype.clone()),
134 Self::new_logical(right, self.dtype.clone()),
135 )
136 }
137 }
138
139 #[inline(always)]
140 pub fn slice(&self, offset: i64, length: usize) -> Self {
141 unsafe { Self::new_logical(self.phys.slice(offset, length), self.dtype.clone()) }
142 }
143
144 #[inline(always)]
145 pub fn field(&self) -> Field {
146 let name = self.phys.ref_field().name();
147 Field::new(name.clone(), LogicalType::dtype(self).clone())
148 }
149
150 #[inline(always)]
151 pub fn physical(&self) -> &ChunkedArray<T> {
152 &self.phys
153 }
154
155 #[inline(always)]
156 pub fn physical_mut(&mut self) -> &mut ChunkedArray<T> {
157 &mut self.phys
158 }
159
160 #[inline(always)]
161 pub fn into_physical(self) -> ChunkedArray<T> {
162 self.phys
163 }
164}