polars_core/datatypes/
_serde.rs

1//! Having `Object<&;static> in [`DataType`] make serde tag the `Deserialize` trait bound 'static
2//! even though we skip serializing `Object`.
3//!
4//! We could use [serde_1712](https://github.com/serde-rs/serde/issues/1712), but that gave problems caused by
5//! [rust_96956](https://github.com/rust-lang/rust/issues/96956), so we make a dummy type without static
6
7use polars_dtype::categorical::CategoricalPhysical;
8use serde::{Deserialize, Serialize};
9
10use super::*;
11
12impl<'a> Deserialize<'a> for DataType {
13    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
14    where
15        D: Deserializer<'a>,
16    {
17        Ok(SerializableDataType::deserialize(deserializer)?.into())
18    }
19}
20
21impl Serialize for DataType {
22    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
23    where
24        S: Serializer,
25    {
26        let dt: SerializableDataType = self.into();
27        dt.serialize(serializer)
28    }
29}
30
31#[cfg(feature = "dsl-schema")]
32impl schemars::JsonSchema for DataType {
33    fn schema_name() -> std::borrow::Cow<'static, str> {
34        SerializableDataType::schema_name()
35    }
36
37    fn schema_id() -> std::borrow::Cow<'static, str> {
38        SerializableDataType::schema_id()
39    }
40
41    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
42        SerializableDataType::json_schema(generator)
43    }
44}
45
46#[derive(Serialize, Deserialize)]
47#[cfg_attr(feature = "dsl-schema", derive(schemars::JsonSchema))]
48#[serde(rename = "DataType")]
49enum SerializableDataType {
50    Boolean,
51    UInt8,
52    UInt16,
53    UInt32,
54    UInt64,
55    UInt128,
56    Int8,
57    Int16,
58    Int32,
59    Int64,
60    Int128,
61    Float32,
62    Float64,
63    String,
64    Binary,
65    BinaryOffset,
66    /// A 32-bit date representing the elapsed time since UNIX epoch (1970-01-01)
67    /// in days (32 bits).
68    Date,
69    /// A 64-bit date representing the elapsed time since UNIX epoch (1970-01-01)
70    /// in the given ms/us/ns TimeUnit (64 bits).
71    Datetime(TimeUnit, Option<TimeZone>),
72    // 64-bit integer representing difference between times in milli|micro|nano seconds
73    Duration(TimeUnit),
74    /// A 64-bit time representing elapsed time since midnight in the given TimeUnit.
75    Time,
76    List(Box<SerializableDataType>),
77    #[cfg(feature = "dtype-array")]
78    Array(Box<SerializableDataType>, usize),
79    Null,
80    #[cfg(feature = "dtype-struct")]
81    Struct(Vec<Field>),
82    // some logical types we cannot know statically, e.g. Datetime
83    Unknown(UnknownKind),
84    #[cfg(feature = "dtype-categorical")]
85    Categorical {
86        name: String,
87        namespace: String,
88        physical: CategoricalPhysical,
89    },
90    #[cfg(feature = "dtype-categorical")]
91    Enum {
92        strings: Series,
93    },
94    #[cfg(feature = "dtype-decimal")]
95    Decimal(usize, usize),
96    #[cfg(feature = "object")]
97    Object(String),
98}
99
100impl From<&DataType> for SerializableDataType {
101    fn from(dt: &DataType) -> Self {
102        use DataType::*;
103        match dt {
104            Boolean => Self::Boolean,
105            UInt8 => Self::UInt8,
106            UInt16 => Self::UInt16,
107            UInt32 => Self::UInt32,
108            UInt64 => Self::UInt64,
109            UInt128 => Self::UInt128,
110            Int8 => Self::Int8,
111            Int16 => Self::Int16,
112            Int32 => Self::Int32,
113            Int64 => Self::Int64,
114            Int128 => Self::Int128,
115            Float32 => Self::Float32,
116            Float64 => Self::Float64,
117            String => Self::String,
118            Binary => Self::Binary,
119            BinaryOffset => Self::BinaryOffset,
120            Date => Self::Date,
121            Datetime(tu, tz) => Self::Datetime(*tu, tz.clone()),
122            Duration(tu) => Self::Duration(*tu),
123            Time => Self::Time,
124            List(dt) => Self::List(Box::new(dt.as_ref().into())),
125            #[cfg(feature = "dtype-array")]
126            Array(dt, width) => Self::Array(Box::new(dt.as_ref().into()), *width),
127            Null => Self::Null,
128            Unknown(kind) => Self::Unknown(*kind),
129            #[cfg(feature = "dtype-struct")]
130            Struct(flds) => Self::Struct(flds.clone()),
131            #[cfg(feature = "dtype-categorical")]
132            Categorical(cats, _) => Self::Categorical {
133                name: cats.name().to_string(),
134                namespace: cats.namespace().to_string(),
135                physical: cats.physical(),
136            },
137            #[cfg(feature = "dtype-categorical")]
138            Enum(fcats, _) => Self::Enum {
139                strings: StringChunked::with_chunk(
140                    PlSmallStr::from_static("categories"),
141                    fcats.categories().clone(),
142                )
143                .into_series(),
144            },
145            #[cfg(feature = "dtype-decimal")]
146            Decimal(precision, scale) => Self::Decimal(*precision, *scale),
147            #[cfg(feature = "object")]
148            Object(name) => Self::Object(name.to_string()),
149        }
150    }
151}
152impl From<SerializableDataType> for DataType {
153    fn from(dt: SerializableDataType) -> Self {
154        use SerializableDataType::*;
155        match dt {
156            Boolean => Self::Boolean,
157            UInt8 => Self::UInt8,
158            UInt16 => Self::UInt16,
159            UInt32 => Self::UInt32,
160            UInt64 => Self::UInt64,
161            UInt128 => Self::UInt128,
162            Int8 => Self::Int8,
163            Int16 => Self::Int16,
164            Int32 => Self::Int32,
165            Int64 => Self::Int64,
166            Int128 => Self::Int128,
167            Float32 => Self::Float32,
168            Float64 => Self::Float64,
169            String => Self::String,
170            Binary => Self::Binary,
171            BinaryOffset => Self::BinaryOffset,
172            Date => Self::Date,
173            Datetime(tu, tz) => Self::Datetime(tu, tz),
174            Duration(tu) => Self::Duration(tu),
175            Time => Self::Time,
176            List(dt) => Self::List(Box::new((*dt).into())),
177            #[cfg(feature = "dtype-array")]
178            Array(dt, width) => Self::Array(Box::new((*dt).into()), width),
179            Null => Self::Null,
180            Unknown(kind) => Self::Unknown(kind),
181            #[cfg(feature = "dtype-struct")]
182            Struct(flds) => Self::Struct(flds),
183            #[cfg(feature = "dtype-categorical")]
184            Categorical {
185                name,
186                namespace,
187                physical,
188            } => {
189                let cats = Categories::new(
190                    PlSmallStr::from(name),
191                    PlSmallStr::from(namespace),
192                    physical,
193                );
194                let mapping = cats.mapping();
195                Self::Categorical(cats, mapping)
196            },
197            #[cfg(feature = "dtype-categorical")]
198            Enum { strings } => {
199                let ca = strings.str().unwrap();
200                let fcats = FrozenCategories::new(ca.iter().flatten()).unwrap();
201                let mapping = fcats.mapping().clone();
202                Self::Enum(fcats, mapping)
203            },
204            #[cfg(feature = "dtype-decimal")]
205            Decimal(precision, scale) => Self::Decimal(precision, scale),
206            #[cfg(feature = "object")]
207            Object(_) => Self::Object("unknown"),
208        }
209    }
210}