1use 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 Float16,
62 Float32,
63 Float64,
64 String,
65 Binary,
66 BinaryOffset,
67 Date,
70 Datetime(TimeUnit, Option<TimeZone>),
73 Duration(TimeUnit),
75 Time,
77 List(Box<SerializableDataType>),
78 #[cfg(feature = "dtype-array")]
79 Array(Box<SerializableDataType>, usize),
80 Null,
81 #[cfg(feature = "dtype-struct")]
82 Struct(Vec<Field>),
83 #[cfg(feature = "dtype-map")]
84 Map(Box<SerializableDataType>, Box<SerializableDataType>),
85 Unknown(UnknownKind),
87 #[cfg(feature = "dtype-categorical")]
88 Categorical {
89 name: String,
90 namespace: String,
91 physical: CategoricalPhysical,
92 },
93 #[cfg(feature = "dtype-categorical")]
94 Enum {
95 strings: Series,
96 },
97 #[cfg(feature = "dtype-decimal")]
98 Decimal(usize, usize),
99 #[cfg(feature = "object")]
100 Object(String),
101 #[cfg(feature = "dtype-extension")]
102 Extension {
103 name: String,
104 metadata: Option<String>,
105 storage: Box<SerializableDataType>,
106 },
107}
108
109impl From<&DataType> for SerializableDataType {
110 fn from(dt: &DataType) -> Self {
111 use DataType::*;
112 match dt {
113 Boolean => Self::Boolean,
114 UInt8 => Self::UInt8,
115 UInt16 => Self::UInt16,
116 UInt32 => Self::UInt32,
117 UInt64 => Self::UInt64,
118 UInt128 => Self::UInt128,
119 Int8 => Self::Int8,
120 Int16 => Self::Int16,
121 Int32 => Self::Int32,
122 Int64 => Self::Int64,
123 Int128 => Self::Int128,
124 Float16 => Self::Float16,
125 Float32 => Self::Float32,
126 Float64 => Self::Float64,
127 String => Self::String,
128 Binary => Self::Binary,
129 BinaryOffset => Self::BinaryOffset,
130 Date => Self::Date,
131 Datetime(tu, tz) => Self::Datetime(*tu, tz.clone()),
132 Duration(tu) => Self::Duration(*tu),
133 Time => Self::Time,
134 List(dt) => Self::List(Box::new(dt.as_ref().into())),
135 #[cfg(feature = "dtype-array")]
136 Array(dt, width) => Self::Array(Box::new(dt.as_ref().into()), *width),
137 Null => Self::Null,
138 Unknown(kind) => Self::Unknown(*kind),
139 #[cfg(feature = "dtype-struct")]
140 Struct(flds) => Self::Struct(flds.clone()),
141 #[cfg(feature = "dtype-map")]
142 Map(key, value) => Self::Map(
143 Box::new(key.as_ref().into()),
144 Box::new(value.as_ref().into()),
145 ),
146 #[cfg(feature = "dtype-categorical")]
147 Categorical(cats, _) => Self::Categorical {
148 name: cats.name().to_string(),
149 namespace: cats.namespace().to_string(),
150 physical: cats.physical(),
151 },
152 #[cfg(feature = "dtype-categorical")]
153 Enum(fcats, _) => Self::Enum {
154 strings: StringChunked::with_chunk(
155 PlSmallStr::from_static("categories"),
156 fcats.categories().clone(),
157 )
158 .into_series(),
159 },
160 #[cfg(feature = "dtype-decimal")]
161 Decimal(precision, scale) => Self::Decimal(*precision, *scale),
162 #[cfg(feature = "object")]
163 Object(name) => Self::Object(name.to_string()),
164 #[cfg(feature = "dtype-extension")]
165 Extension(typ, storage) => Self::Extension {
166 name: typ.name().to_string(),
167 metadata: typ.serialize_metadata().map(|s| s.into_owned()),
168 storage: Box::new(SerializableDataType::from(storage.as_ref())),
169 },
170 }
171 }
172}
173impl From<SerializableDataType> for DataType {
174 fn from(dt: SerializableDataType) -> Self {
175 use SerializableDataType::*;
176 match dt {
177 Boolean => Self::Boolean,
178 UInt8 => Self::UInt8,
179 UInt16 => Self::UInt16,
180 UInt32 => Self::UInt32,
181 UInt64 => Self::UInt64,
182 UInt128 => Self::UInt128,
183 Int8 => Self::Int8,
184 Int16 => Self::Int16,
185 Int32 => Self::Int32,
186 Int64 => Self::Int64,
187 Int128 => Self::Int128,
188 Float16 => Self::Float16,
189 Float32 => Self::Float32,
190 Float64 => Self::Float64,
191 String => Self::String,
192 Binary => Self::Binary,
193 BinaryOffset => Self::BinaryOffset,
194 Date => Self::Date,
195 Datetime(tu, tz) => Self::Datetime(tu, tz),
196 Duration(tu) => Self::Duration(tu),
197 Time => Self::Time,
198 List(dt) => Self::List(Box::new((*dt).into())),
199 #[cfg(feature = "dtype-array")]
200 Array(dt, width) => Self::Array(Box::new((*dt).into()), width),
201 Null => Self::Null,
202 Unknown(kind) => Self::Unknown(kind),
203 #[cfg(feature = "dtype-struct")]
204 Struct(flds) => Self::Struct(flds),
205 #[cfg(feature = "dtype-map")]
206 Map(key, value) => Self::Map(Box::new((*key).into()), Box::new((*value).into())),
207 #[cfg(feature = "dtype-categorical")]
208 Categorical {
209 name,
210 namespace,
211 physical,
212 } => {
213 let cats = Categories::new(
214 PlSmallStr::from(name),
215 PlSmallStr::from(namespace),
216 physical,
217 );
218 let mapping = cats.mapping();
219 Self::Categorical(cats, mapping)
220 },
221 #[cfg(feature = "dtype-categorical")]
222 Enum { strings } => {
223 let ca = strings.str().unwrap();
224 let fcats = FrozenCategories::new(ca.iter().flatten()).unwrap();
225 let mapping = fcats.mapping().clone();
226 Self::Enum(fcats, mapping)
227 },
228 #[cfg(feature = "dtype-decimal")]
229 Decimal(precision, scale) => Self::Decimal(precision, scale),
230 #[cfg(feature = "object")]
231 Object(_) => Self::Object("unknown"),
232 #[cfg(feature = "dtype-extension")]
233 Extension {
234 name,
235 metadata,
236 storage,
237 } => {
238 let storage = DataType::from(*storage);
239 let ext_type = crate::datatypes::extension::get_extension_type_or_generic(
240 &name,
241 &storage,
242 metadata.as_deref(),
243 );
244 Self::Extension(ext_type, Box::new(storage))
245 },
246 }
247 }
248}