polars_core/scalar/
mod.rs

1mod from;
2mod new;
3#[cfg(any(feature = "serde", feature = "dsl-schema"))]
4mod serde;
5
6use std::hash::Hash;
7
8use polars_error::PolarsResult;
9use polars_utils::IdxSize;
10use polars_utils::pl_str::PlSmallStr;
11
12use crate::chunked_array::cast::CastOptions;
13use crate::datatypes::{AnyValue, DataType};
14use crate::prelude::{Column, Series};
15
16#[derive(Clone, Debug, PartialEq)]
17pub struct Scalar {
18    dtype: DataType,
19    value: AnyValue<'static>,
20}
21
22impl Hash for Scalar {
23    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
24        self.dtype.hash(state);
25        self.value.hash_impl(state, true);
26    }
27}
28
29impl Default for Scalar {
30    fn default() -> Self {
31        Self {
32            dtype: DataType::Null,
33            value: AnyValue::Null,
34        }
35    }
36}
37
38impl Scalar {
39    #[inline(always)]
40    pub const fn new(dtype: DataType, value: AnyValue<'static>) -> Self {
41        Self { dtype, value }
42    }
43
44    pub const fn null(dtype: DataType) -> Self {
45        Self::new(dtype, AnyValue::Null)
46    }
47
48    pub fn new_idxsize(value: IdxSize) -> Self {
49        value.into()
50    }
51
52    pub fn cast_with_options(self, dtype: &DataType, options: CastOptions) -> PolarsResult<Self> {
53        if self.dtype() == dtype {
54            return Ok(self);
55        }
56
57        // @Optimize: If we have fully fleshed out casting semantics, we could just specify the
58        // cast on AnyValue.
59        let s = self
60            .into_series(PlSmallStr::from_static("scalar"))
61            .cast_with_options(dtype, options)?;
62        let value = s.get(0).unwrap();
63        Ok(Self::new(s.dtype().clone(), value.into_static()))
64    }
65
66    #[inline(always)]
67    pub fn is_null(&self) -> bool {
68        self.value.is_null()
69    }
70
71    #[inline(always)]
72    pub fn is_nan(&self) -> bool {
73        self.value.is_nan()
74    }
75
76    #[inline(always)]
77    pub fn into_value(self) -> AnyValue<'static> {
78        self.value
79    }
80
81    #[inline(always)]
82    pub fn value(&self) -> &AnyValue<'static> {
83        &self.value
84    }
85
86    pub fn as_any_value(&self) -> AnyValue<'_> {
87        self.value
88            .strict_cast(&self.dtype)
89            .unwrap_or_else(|| self.value.clone())
90    }
91
92    pub fn into_series(self, name: PlSmallStr) -> Series {
93        Series::from_any_values_and_dtype(name, &[self.as_any_value()], &self.dtype, true).unwrap()
94    }
95
96    /// Turn a scalar into a column with `length=1`.
97    pub fn into_column(self, name: PlSmallStr) -> Column {
98        Column::new_scalar(name, self, 1)
99    }
100
101    #[inline(always)]
102    pub fn dtype(&self) -> &DataType {
103        &self.dtype
104    }
105
106    #[inline(always)]
107    pub fn update(&mut self, value: AnyValue<'static>) {
108        self.value = value;
109    }
110
111    #[inline(always)]
112    pub fn with_value(mut self, value: AnyValue<'static>) -> Self {
113        self.update(value);
114        self
115    }
116
117    #[inline(always)]
118    pub fn any_value_mut(&mut self) -> &mut AnyValue<'static> {
119        &mut self.value
120    }
121
122    pub fn to_physical(mut self) -> Scalar {
123        self.dtype = self.dtype.to_physical();
124        self.value = self.value.to_physical();
125        self
126    }
127}