Path: blob/main/crates/polars-core/src/series/ops/downcast.rs
8458 views
#![allow(unsafe_op_in_unsafe_fn)]1use crate::prelude::*;2use crate::series::implementations::null::NullChunked;34macro_rules! unpack_chunked_err {5($series:expr => $name:expr) => {6polars_err!(SchemaMismatch: "invalid series dtype: expected `{}`, got `{}` for series with name `{}`", $name, $series.dtype(), $series.name())7};8}910macro_rules! try_unpack_chunked {11($series:expr, $expected:pat $(if $guard: expr)? => $ca:ty) => {12match $series.dtype() {13$expected $(if $guard)? => {14// Check downcast in debug compiles15#[cfg(debug_assertions)]16{17Some($series.as_ref().as_any().downcast_ref::<$ca>().unwrap())18}19#[cfg(not(debug_assertions))]20unsafe {21Some(&*($series.as_ref() as *const dyn SeriesTrait as *const $ca))22}23},24_ => None,25}26};27}2829impl Series {30/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int8`]31pub fn try_i8(&self) -> Option<&Int8Chunked> {32try_unpack_chunked!(self, DataType::Int8 => Int8Chunked)33}3435/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int16`]36pub fn try_i16(&self) -> Option<&Int16Chunked> {37try_unpack_chunked!(self, DataType::Int16 => Int16Chunked)38}3940/// Unpack to [`ChunkedArray`]41/// ```42/// # use polars_core::prelude::*;43/// let s = Series::new("foo".into(), [1i32 ,2, 3]);44/// let s_squared: Series = s.i32()45/// .unwrap()46/// .into_iter()47/// .map(|opt_v| {48/// match opt_v {49/// Some(v) => Some(v * v),50/// None => None, // null value51/// }52/// }).collect();53/// ```54/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int32`]55pub fn try_i32(&self) -> Option<&Int32Chunked> {56try_unpack_chunked!(self, DataType::Int32 => Int32Chunked)57}5859/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int64`]60pub fn try_i64(&self) -> Option<&Int64Chunked> {61try_unpack_chunked!(self, DataType::Int64 => Int64Chunked)62}6364/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int128`]65#[cfg(feature = "dtype-i128")]66pub fn try_i128(&self) -> Option<&Int128Chunked> {67try_unpack_chunked!(self, DataType::Int128 => Int128Chunked)68}6970/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float16`]71#[cfg(feature = "dtype-f16")]72pub fn try_f16(&self) -> Option<&Float16Chunked> {73try_unpack_chunked!(self, DataType::Float16 => Float16Chunked)74}7576/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float32`]77pub fn try_f32(&self) -> Option<&Float32Chunked> {78try_unpack_chunked!(self, DataType::Float32 => Float32Chunked)79}8081/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float64`]82pub fn try_f64(&self) -> Option<&Float64Chunked> {83try_unpack_chunked!(self, DataType::Float64 => Float64Chunked)84}8586/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt8`]87pub fn try_u8(&self) -> Option<&UInt8Chunked> {88try_unpack_chunked!(self, DataType::UInt8 => UInt8Chunked)89}9091/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt16`]92pub fn try_u16(&self) -> Option<&UInt16Chunked> {93try_unpack_chunked!(self, DataType::UInt16 => UInt16Chunked)94}9596/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt32`]97pub fn try_u32(&self) -> Option<&UInt32Chunked> {98try_unpack_chunked!(self, DataType::UInt32 => UInt32Chunked)99}100101/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt64`]102pub fn try_u64(&self) -> Option<&UInt64Chunked> {103try_unpack_chunked!(self, DataType::UInt64 => UInt64Chunked)104}105106/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt128`]107#[cfg(feature = "dtype-u128")]108pub fn try_u128(&self) -> Option<&UInt128Chunked> {109try_unpack_chunked!(self, DataType::UInt128 => UInt128Chunked)110}111112/// Unpack to [`ChunkedArray`] of dtype [`DataType::Boolean`]113pub fn try_bool(&self) -> Option<&BooleanChunked> {114try_unpack_chunked!(self, DataType::Boolean => BooleanChunked)115}116117/// Unpack to [`ChunkedArray`] of dtype [`DataType::String`]118pub fn try_str(&self) -> Option<&StringChunked> {119try_unpack_chunked!(self, DataType::String => StringChunked)120}121122/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]123pub fn try_binary(&self) -> Option<&BinaryChunked> {124try_unpack_chunked!(self, DataType::Binary => BinaryChunked)125}126127/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]128pub fn try_binary_offset(&self) -> Option<&BinaryOffsetChunked> {129try_unpack_chunked!(self, DataType::BinaryOffset => BinaryOffsetChunked)130}131132/// Unpack to [`ChunkedArray`] of dtype [`DataType::Time`]133#[cfg(feature = "dtype-time")]134pub fn try_time(&self) -> Option<&TimeChunked> {135try_unpack_chunked!(self, DataType::Time => TimeChunked)136}137138/// Unpack to [`ChunkedArray`] of dtype [`DataType::Date`]139#[cfg(feature = "dtype-date")]140pub fn try_date(&self) -> Option<&DateChunked> {141try_unpack_chunked!(self, DataType::Date => DateChunked)142}143144/// Unpack to [`ChunkedArray`] of dtype [`DataType::Datetime`]145#[cfg(feature = "dtype-datetime")]146pub fn try_datetime(&self) -> Option<&DatetimeChunked> {147try_unpack_chunked!(self, DataType::Datetime(_, _) => DatetimeChunked)148}149150/// Unpack to [`ChunkedArray`] of dtype [`DataType::Duration`]151#[cfg(feature = "dtype-duration")]152pub fn try_duration(&self) -> Option<&DurationChunked> {153try_unpack_chunked!(self, DataType::Duration(_) => DurationChunked)154}155156/// Unpack to [`ChunkedArray`] of dtype [`DataType::Decimal`]157#[cfg(feature = "dtype-decimal")]158pub fn try_decimal(&self) -> Option<&DecimalChunked> {159try_unpack_chunked!(self, DataType::Decimal(_, _) => DecimalChunked)160}161162/// Unpack to [`ChunkedArray`] of dtype list163pub fn try_list(&self) -> Option<&ListChunked> {164try_unpack_chunked!(self, DataType::List(_) => ListChunked)165}166167/// Unpack to [`ChunkedArray`] of dtype [`DataType::Array`]168#[cfg(feature = "dtype-array")]169pub fn try_array(&self) -> Option<&ArrayChunked> {170try_unpack_chunked!(self, DataType::Array(_, _) => ArrayChunked)171}172173#[cfg(feature = "dtype-categorical")]174pub fn try_cat<T: PolarsCategoricalType>(&self) -> Option<&CategoricalChunked<T>> {175try_unpack_chunked!(self, dt @ DataType::Enum(_, _) | dt @ DataType::Categorical(_, _) if dt.cat_physical().unwrap() == T::physical() => CategoricalChunked<T>)176}177178/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt8.179#[cfg(feature = "dtype-categorical")]180pub fn try_cat8(&self) -> Option<&Categorical8Chunked> {181self.try_cat::<Categorical8Type>()182}183184#[cfg(feature = "dtype-categorical")]185pub fn try_cat16(&self) -> Option<&Categorical16Chunked> {186self.try_cat::<Categorical16Type>()187}188189#[cfg(feature = "dtype-categorical")]190pub fn try_cat32(&self) -> Option<&Categorical32Chunked> {191self.try_cat::<Categorical32Type>()192}193194/// Unpack to [`ExtensionChunked`] of dtype [`DataType::Extension`].195#[cfg(feature = "dtype-extension")]196pub fn try_ext(&self) -> Option<&ExtensionChunked> {197try_unpack_chunked!(self, DataType::Extension(_, _) => ExtensionChunked)198}199200/// Unpack to [`ChunkedArray`] of dtype [`DataType::Struct`]201#[cfg(feature = "dtype-struct")]202pub fn try_struct(&self) -> Option<&StructChunked> {203#[cfg(debug_assertions)]204{205if let DataType::Struct(_) = self.dtype() {206let any = self.as_any();207assert!(any.is::<StructChunked>());208}209}210try_unpack_chunked!(self, DataType::Struct(_) => StructChunked)211}212213/// Unpack to [`ChunkedArray`] of dtype [`DataType::Null`]214pub fn try_null(&self) -> Option<&NullChunked> {215try_unpack_chunked!(self, DataType::Null => NullChunked)216}217/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int8`]218pub fn i8(&self) -> PolarsResult<&Int8Chunked> {219self.try_i8()220.ok_or_else(|| unpack_chunked_err!(self => "Int8"))221}222223/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int16`]224pub fn i16(&self) -> PolarsResult<&Int16Chunked> {225self.try_i16()226.ok_or_else(|| unpack_chunked_err!(self => "Int16"))227}228229/// Unpack to [`ChunkedArray`]230/// ```231/// # use polars_core::prelude::*;232/// let s = Series::new("foo".into(), [1i32 ,2, 3]);233/// let s_squared: Series = s.i32()234/// .unwrap()235/// .into_iter()236/// .map(|opt_v| {237/// match opt_v {238/// Some(v) => Some(v * v),239/// None => None, // null value240/// }241/// }).collect();242/// ```243/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int32`]244pub fn i32(&self) -> PolarsResult<&Int32Chunked> {245self.try_i32()246.ok_or_else(|| unpack_chunked_err!(self => "Int32"))247}248249/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int64`]250pub fn i64(&self) -> PolarsResult<&Int64Chunked> {251self.try_i64()252.ok_or_else(|| unpack_chunked_err!(self => "Int64"))253}254255/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int128`]256#[cfg(feature = "dtype-i128")]257pub fn i128(&self) -> PolarsResult<&Int128Chunked> {258self.try_i128()259.ok_or_else(|| unpack_chunked_err!(self => "Int128"))260}261262/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float16`]263#[cfg(feature = "dtype-f16")]264pub fn f16(&self) -> PolarsResult<&Float16Chunked> {265self.try_f16()266.ok_or_else(|| unpack_chunked_err!(self => "Float16"))267}268269/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float32`]270pub fn f32(&self) -> PolarsResult<&Float32Chunked> {271self.try_f32()272.ok_or_else(|| unpack_chunked_err!(self => "Float32"))273}274275/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float64`]276pub fn f64(&self) -> PolarsResult<&Float64Chunked> {277self.try_f64()278.ok_or_else(|| unpack_chunked_err!(self => "Float64"))279}280281/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt8`]282pub fn u8(&self) -> PolarsResult<&UInt8Chunked> {283self.try_u8()284.ok_or_else(|| unpack_chunked_err!(self => "UInt8"))285}286287/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt16`]288pub fn u16(&self) -> PolarsResult<&UInt16Chunked> {289self.try_u16()290.ok_or_else(|| unpack_chunked_err!(self => "UInt16"))291}292293/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt32`]294pub fn u32(&self) -> PolarsResult<&UInt32Chunked> {295self.try_u32()296.ok_or_else(|| unpack_chunked_err!(self => "UInt32"))297}298299/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt64`]300pub fn u64(&self) -> PolarsResult<&UInt64Chunked> {301self.try_u64()302.ok_or_else(|| unpack_chunked_err!(self => "UInt64"))303}304305/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt128`]306#[cfg(feature = "dtype-u128")]307pub fn u128(&self) -> PolarsResult<&UInt128Chunked> {308self.try_u128()309.ok_or_else(|| unpack_chunked_err!(self => "UInt128"))310}311312/// Unpack to [`ChunkedArray`] of dtype [`DataType::Boolean`]313pub fn bool(&self) -> PolarsResult<&BooleanChunked> {314self.try_bool()315.ok_or_else(|| unpack_chunked_err!(self => "Boolean"))316}317318/// Unpack to [`ChunkedArray`] of dtype [`DataType::String`]319pub fn str(&self) -> PolarsResult<&StringChunked> {320self.try_str()321.ok_or_else(|| unpack_chunked_err!(self => "String"))322}323324/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]325pub fn binary(&self) -> PolarsResult<&BinaryChunked> {326self.try_binary()327.ok_or_else(|| unpack_chunked_err!(self => "Binary"))328}329330/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]331pub fn binary_offset(&self) -> PolarsResult<&BinaryOffsetChunked> {332self.try_binary_offset()333.ok_or_else(|| unpack_chunked_err!(self => "BinaryOffset"))334}335336/// Unpack to [`ChunkedArray`] of dtype [`DataType::Time`]337#[cfg(feature = "dtype-time")]338pub fn time(&self) -> PolarsResult<&TimeChunked> {339self.try_time()340.ok_or_else(|| unpack_chunked_err!(self => "Time"))341}342343/// Unpack to [`ChunkedArray`] of dtype [`DataType::Date`]344#[cfg(feature = "dtype-date")]345pub fn date(&self) -> PolarsResult<&DateChunked> {346self.try_date()347.ok_or_else(|| unpack_chunked_err!(self => "Date"))348}349350/// Unpack to [`ChunkedArray`] of dtype [`DataType::Datetime`]351#[cfg(feature = "dtype-datetime")]352pub fn datetime(&self) -> PolarsResult<&DatetimeChunked> {353self.try_datetime()354.ok_or_else(|| unpack_chunked_err!(self => "Datetime"))355}356357/// Unpack to [`ChunkedArray`] of dtype [`DataType::Duration`]358#[cfg(feature = "dtype-duration")]359pub fn duration(&self) -> PolarsResult<&DurationChunked> {360self.try_duration()361.ok_or_else(|| unpack_chunked_err!(self => "Duration"))362}363364/// Unpack to [`ChunkedArray`] of dtype [`DataType::Decimal`]365#[cfg(feature = "dtype-decimal")]366pub fn decimal(&self) -> PolarsResult<&DecimalChunked> {367self.try_decimal()368.ok_or_else(|| unpack_chunked_err!(self => "Decimal"))369}370371/// Unpack to [`ChunkedArray`] of dtype list372pub fn list(&self) -> PolarsResult<&ListChunked> {373self.try_list()374.ok_or_else(|| unpack_chunked_err!(self => "List"))375}376377/// Unpack to [`ChunkedArray`] of dtype [`DataType::Array`]378#[cfg(feature = "dtype-array")]379pub fn array(&self) -> PolarsResult<&ArrayChunked> {380self.try_array()381.ok_or_else(|| unpack_chunked_err!(self => "Array"))382}383384/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`].385#[cfg(feature = "dtype-categorical")]386pub fn cat<T: PolarsCategoricalType>(&self) -> PolarsResult<&CategoricalChunked<T>> {387self.try_cat::<T>()388.ok_or_else(|| unpack_chunked_err!(self => "Enum | Categorical"))389}390391/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt8.392#[cfg(feature = "dtype-categorical")]393pub fn cat8(&self) -> PolarsResult<&CategoricalChunked<Categorical8Type>> {394self.try_cat8()395.ok_or_else(|| unpack_chunked_err!(self => "Enum8 | Categorical8"))396}397398/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt16.399#[cfg(feature = "dtype-categorical")]400pub fn cat16(&self) -> PolarsResult<&CategoricalChunked<Categorical16Type>> {401self.try_cat16()402.ok_or_else(|| unpack_chunked_err!(self => "Enum16 | Categorical16"))403}404405/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt32.406#[cfg(feature = "dtype-categorical")]407pub fn cat32(&self) -> PolarsResult<&CategoricalChunked<Categorical32Type>> {408self.try_cat32()409.ok_or_else(|| unpack_chunked_err!(self => "Enum32 | Categorical32"))410}411412/// Unpack to [`ChunkedArray`] of dtype [`DataType::Struct`]413#[cfg(feature = "dtype-struct")]414pub fn struct_(&self) -> PolarsResult<&StructChunked> {415#[cfg(debug_assertions)]416{417if let DataType::Struct(_) = self.dtype() {418let any = self.as_any();419assert!(any.is::<StructChunked>());420}421}422423self.try_struct()424.ok_or_else(|| unpack_chunked_err!(self => "Struct"))425}426427/// Unpack to [`ExtensionChunked`] of dtype [`DataType::Extension`].428#[cfg(feature = "dtype-extension")]429pub fn ext(&self) -> PolarsResult<&ExtensionChunked> {430self.try_ext()431.ok_or_else(|| unpack_chunked_err!(self => "Extension"))432}433434/// Unpack to [`ChunkedArray`] of dtype [`DataType::Null`]435pub fn null(&self) -> PolarsResult<&NullChunked> {436self.try_null()437.ok_or_else(|| unpack_chunked_err!(self => "Null"))438}439}440441442