polars_core/series/ops/
downcast.rs1use crate::prelude::*;
2use crate::series::implementations::null::NullChunked;
3
4macro_rules! unpack_chunked_err {
5 ($series:expr => $name:expr) => {
6 polars_err!(SchemaMismatch: "invalid series dtype: expected `{}`, got `{}` for series with name `{}`", $name, $series.dtype(), $series.name())
7 };
8}
9
10macro_rules! try_unpack_chunked {
11 ($series:expr, $expected:pat => $ca:ty) => {
12 match $series.dtype() {
13 $expected => {
14 #[cfg(debug_assertions)]
16 {
17 Some($series.as_ref().as_any().downcast_ref::<$ca>().unwrap())
18 }
19 #[cfg(not(debug_assertions))]
20 unsafe {
21 Some(&*($series.as_ref() as *const dyn SeriesTrait as *const $ca))
22 }
23 },
24 _ => None,
25 }
26 };
27}
28
29impl Series {
30 pub fn try_i8(&self) -> Option<&Int8Chunked> {
32 try_unpack_chunked!(self, DataType::Int8 => Int8Chunked)
33 }
34
35 pub fn try_i16(&self) -> Option<&Int16Chunked> {
37 try_unpack_chunked!(self, DataType::Int16 => Int16Chunked)
38 }
39
40 pub fn try_i32(&self) -> Option<&Int32Chunked> {
56 try_unpack_chunked!(self, DataType::Int32 => Int32Chunked)
57 }
58
59 pub fn try_i64(&self) -> Option<&Int64Chunked> {
61 try_unpack_chunked!(self, DataType::Int64 => Int64Chunked)
62 }
63
64 #[cfg(feature = "dtype-i128")]
66 pub fn try_i128(&self) -> Option<&Int128Chunked> {
67 try_unpack_chunked!(self, DataType::Int128 => Int128Chunked)
68 }
69
70 pub fn try_f32(&self) -> Option<&Float32Chunked> {
72 try_unpack_chunked!(self, DataType::Float32 => Float32Chunked)
73 }
74
75 pub fn try_f64(&self) -> Option<&Float64Chunked> {
77 try_unpack_chunked!(self, DataType::Float64 => Float64Chunked)
78 }
79
80 pub fn try_u8(&self) -> Option<&UInt8Chunked> {
82 try_unpack_chunked!(self, DataType::UInt8 => UInt8Chunked)
83 }
84
85 pub fn try_u16(&self) -> Option<&UInt16Chunked> {
87 try_unpack_chunked!(self, DataType::UInt16 => UInt16Chunked)
88 }
89
90 pub fn try_u32(&self) -> Option<&UInt32Chunked> {
92 try_unpack_chunked!(self, DataType::UInt32 => UInt32Chunked)
93 }
94
95 pub fn try_u64(&self) -> Option<&UInt64Chunked> {
97 try_unpack_chunked!(self, DataType::UInt64 => UInt64Chunked)
98 }
99
100 pub fn try_bool(&self) -> Option<&BooleanChunked> {
102 try_unpack_chunked!(self, DataType::Boolean => BooleanChunked)
103 }
104
105 pub fn try_str(&self) -> Option<&StringChunked> {
107 try_unpack_chunked!(self, DataType::String => StringChunked)
108 }
109
110 pub fn try_binary(&self) -> Option<&BinaryChunked> {
112 try_unpack_chunked!(self, DataType::Binary => BinaryChunked)
113 }
114
115 pub fn try_binary_offset(&self) -> Option<&BinaryOffsetChunked> {
117 try_unpack_chunked!(self, DataType::BinaryOffset => BinaryOffsetChunked)
118 }
119
120 #[cfg(feature = "dtype-time")]
122 pub fn try_time(&self) -> Option<&TimeChunked> {
123 try_unpack_chunked!(self, DataType::Time => TimeChunked)
124 }
125
126 #[cfg(feature = "dtype-date")]
128 pub fn try_date(&self) -> Option<&DateChunked> {
129 try_unpack_chunked!(self, DataType::Date => DateChunked)
130 }
131
132 #[cfg(feature = "dtype-datetime")]
134 pub fn try_datetime(&self) -> Option<&DatetimeChunked> {
135 try_unpack_chunked!(self, DataType::Datetime(_, _) => DatetimeChunked)
136 }
137
138 #[cfg(feature = "dtype-duration")]
140 pub fn try_duration(&self) -> Option<&DurationChunked> {
141 try_unpack_chunked!(self, DataType::Duration(_) => DurationChunked)
142 }
143
144 #[cfg(feature = "dtype-decimal")]
146 pub fn try_decimal(&self) -> Option<&DecimalChunked> {
147 try_unpack_chunked!(self, DataType::Decimal(_, _) => DecimalChunked)
148 }
149
150 pub fn try_list(&self) -> Option<&ListChunked> {
152 try_unpack_chunked!(self, DataType::List(_) => ListChunked)
153 }
154
155 #[cfg(feature = "dtype-array")]
157 pub fn try_array(&self) -> Option<&ArrayChunked> {
158 try_unpack_chunked!(self, DataType::Array(_, _) => ArrayChunked)
159 }
160
161 #[cfg(feature = "dtype-categorical")]
163 pub fn try_categorical(&self) -> Option<&CategoricalChunked> {
164 try_unpack_chunked!(self, DataType::Categorical(_, _) | DataType::Enum(_, _) => CategoricalChunked)
165 }
166
167 #[cfg(feature = "dtype-struct")]
169 pub fn try_struct(&self) -> Option<&StructChunked> {
170 #[cfg(debug_assertions)]
171 {
172 if let DataType::Struct(_) = self.dtype() {
173 let any = self.as_any();
174 assert!(any.is::<StructChunked>());
175 }
176 }
177 try_unpack_chunked!(self, DataType::Struct(_) => StructChunked)
178 }
179
180 pub fn try_null(&self) -> Option<&NullChunked> {
182 try_unpack_chunked!(self, DataType::Null => NullChunked)
183 }
184 pub fn i8(&self) -> PolarsResult<&Int8Chunked> {
186 self.try_i8()
187 .ok_or_else(|| unpack_chunked_err!(self => "Int8"))
188 }
189
190 pub fn i16(&self) -> PolarsResult<&Int16Chunked> {
192 self.try_i16()
193 .ok_or_else(|| unpack_chunked_err!(self => "Int16"))
194 }
195
196 pub fn i32(&self) -> PolarsResult<&Int32Chunked> {
212 self.try_i32()
213 .ok_or_else(|| unpack_chunked_err!(self => "Int32"))
214 }
215
216 pub fn i64(&self) -> PolarsResult<&Int64Chunked> {
218 self.try_i64()
219 .ok_or_else(|| unpack_chunked_err!(self => "Int64"))
220 }
221
222 #[cfg(feature = "dtype-i128")]
224 pub fn i128(&self) -> PolarsResult<&Int128Chunked> {
225 self.try_i128()
226 .ok_or_else(|| unpack_chunked_err!(self => "Int128"))
227 }
228
229 pub fn f32(&self) -> PolarsResult<&Float32Chunked> {
231 self.try_f32()
232 .ok_or_else(|| unpack_chunked_err!(self => "Float32"))
233 }
234
235 pub fn f64(&self) -> PolarsResult<&Float64Chunked> {
237 self.try_f64()
238 .ok_or_else(|| unpack_chunked_err!(self => "Float64"))
239 }
240
241 pub fn u8(&self) -> PolarsResult<&UInt8Chunked> {
243 self.try_u8()
244 .ok_or_else(|| unpack_chunked_err!(self => "UInt8"))
245 }
246
247 pub fn u16(&self) -> PolarsResult<&UInt16Chunked> {
249 self.try_u16()
250 .ok_or_else(|| unpack_chunked_err!(self => "UInt16"))
251 }
252
253 pub fn u32(&self) -> PolarsResult<&UInt32Chunked> {
255 self.try_u32()
256 .ok_or_else(|| unpack_chunked_err!(self => "UInt32"))
257 }
258
259 pub fn u64(&self) -> PolarsResult<&UInt64Chunked> {
261 self.try_u64()
262 .ok_or_else(|| unpack_chunked_err!(self => "UInt64"))
263 }
264
265 pub fn bool(&self) -> PolarsResult<&BooleanChunked> {
267 self.try_bool()
268 .ok_or_else(|| unpack_chunked_err!(self => "Boolean"))
269 }
270
271 pub fn str(&self) -> PolarsResult<&StringChunked> {
273 self.try_str()
274 .ok_or_else(|| unpack_chunked_err!(self => "String"))
275 }
276
277 pub fn binary(&self) -> PolarsResult<&BinaryChunked> {
279 self.try_binary()
280 .ok_or_else(|| unpack_chunked_err!(self => "Binary"))
281 }
282
283 pub fn binary_offset(&self) -> PolarsResult<&BinaryOffsetChunked> {
285 self.try_binary_offset()
286 .ok_or_else(|| unpack_chunked_err!(self => "BinaryOffset"))
287 }
288
289 #[cfg(feature = "dtype-time")]
291 pub fn time(&self) -> PolarsResult<&TimeChunked> {
292 self.try_time()
293 .ok_or_else(|| unpack_chunked_err!(self => "Time"))
294 }
295
296 #[cfg(feature = "dtype-date")]
298 pub fn date(&self) -> PolarsResult<&DateChunked> {
299 self.try_date()
300 .ok_or_else(|| unpack_chunked_err!(self => "Date"))
301 }
302
303 #[cfg(feature = "dtype-datetime")]
305 pub fn datetime(&self) -> PolarsResult<&DatetimeChunked> {
306 self.try_datetime()
307 .ok_or_else(|| unpack_chunked_err!(self => "Datetime"))
308 }
309
310 #[cfg(feature = "dtype-duration")]
312 pub fn duration(&self) -> PolarsResult<&DurationChunked> {
313 self.try_duration()
314 .ok_or_else(|| unpack_chunked_err!(self => "Duration"))
315 }
316
317 #[cfg(feature = "dtype-decimal")]
319 pub fn decimal(&self) -> PolarsResult<&DecimalChunked> {
320 self.try_decimal()
321 .ok_or_else(|| unpack_chunked_err!(self => "Decimal"))
322 }
323
324 pub fn list(&self) -> PolarsResult<&ListChunked> {
326 self.try_list()
327 .ok_or_else(|| unpack_chunked_err!(self => "List"))
328 }
329
330 #[cfg(feature = "dtype-array")]
332 pub fn array(&self) -> PolarsResult<&ArrayChunked> {
333 self.try_array()
334 .ok_or_else(|| unpack_chunked_err!(self => "FixedSizeList"))
335 }
336
337 #[cfg(feature = "dtype-categorical")]
339 pub fn categorical(&self) -> PolarsResult<&CategoricalChunked> {
340 self.try_categorical()
341 .ok_or_else(|| unpack_chunked_err!(self => "Enum | Categorical"))
342 }
343
344 #[cfg(feature = "dtype-struct")]
346 pub fn struct_(&self) -> PolarsResult<&StructChunked> {
347 #[cfg(debug_assertions)]
348 {
349 if let DataType::Struct(_) = self.dtype() {
350 let any = self.as_any();
351 assert!(any.is::<StructChunked>());
352 }
353 }
354
355 self.try_struct()
356 .ok_or_else(|| unpack_chunked_err!(self => "Struct"))
357 }
358
359 pub fn null(&self) -> PolarsResult<&NullChunked> {
361 self.try_null()
362 .ok_or_else(|| unpack_chunked_err!(self => "Null"))
363 }
364}