1#![allow(deprecated)]
2#[cfg(feature = "typeid")]
3use std::any::TypeId;
4use std::error::Error;
5use std::str::FromStr;
6
7mod enum_def;
8mod struct_def;
9mod union_def;
10
11use serde::{Deserialize, Serialize};
12
13pub use self::enum_def::{EnumDefinition, EnumVariant};
14pub use self::struct_def::StructDefinition;
15pub use self::union_def::UnionDefinition;
16use crate::Field;
17
18#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
19#[must_use]
20#[serde(tag = "type")]
22#[allow(clippy::exhaustive_enums)]
23pub enum TypeDefinition {
24 #[serde(rename = "struct")]
26 Struct(StructDefinition),
27 #[serde(rename = "enum")]
29 Enum(EnumDefinition),
30 #[serde(rename = "union")]
32 Union(UnionDefinition),
33}
34
35impl TypeDefinition {
36 #[must_use]
38 pub fn name(&self) -> &str {
39 match self {
40 TypeDefinition::Struct(v) => &v.name,
41 TypeDefinition::Enum(v) => &v.name,
42 TypeDefinition::Union(v) => &v.name,
43 }
44 }
45}
46
47#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
48#[serde(rename_all = "lowercase")]
49#[must_use]
50#[allow(clippy::exhaustive_enums)]
51pub enum Type {
53 I8,
55 I16,
57 I32,
59 I64,
61 U8,
63 U16,
65 U32,
67 U64,
69 F32,
71 F64,
73 Bool,
75 String,
77 Datetime,
79 Bytes,
81 Named(String),
83 List {
85 #[serde(rename = "type")]
87 #[cfg_attr(feature = "parser", serde(deserialize_with = "crate::types::box_type_signature"))]
88 #[cfg_attr(
89 feature = "yaml",
90 serde(serialize_with = "serde_yaml::with::singleton_map::serialize")
91 )]
92 ty: Box<Type>,
93 },
94 Optional {
96 #[serde(rename = "type")]
98 #[cfg_attr(feature = "parser", serde(deserialize_with = "crate::types::box_type_signature"))]
99 #[cfg_attr(
100 feature = "yaml",
101 serde(serialize_with = "serde_yaml::with::singleton_map::serialize")
102 )]
103 ty: Box<Type>,
104 },
105 Map {
107 #[cfg_attr(feature = "parser", serde(deserialize_with = "crate::types::box_type_signature"))]
109 #[cfg_attr(
110 feature = "yaml",
111 serde(serialize_with = "serde_yaml::with::singleton_map::serialize")
112 )]
113 key: Box<Type>,
114 #[cfg_attr(feature = "parser", serde(deserialize_with = "crate::types::box_type_signature"))]
116 #[cfg_attr(
117 feature = "yaml",
118 serde(serialize_with = "serde_yaml::with::singleton_map::serialize")
119 )]
120 value: Box<Type>,
121 },
122 #[deprecated = "Links are deprecated, use the require/provides interface instead."]
124 Link {
125 #[serde(default)]
127 schemas: Vec<String>,
128 },
129 Object,
131 AnonymousStruct(
133 Vec<Field>,
135 ),
136}
137
138impl Type {
139 #[must_use]
140 #[cfg(feature = "typeid")]
141 pub fn to_type_id(&self) -> TypeId {
142 match self {
143 Type::I8 => TypeId::of::<i8>(),
144 Type::I16 => TypeId::of::<i16>(),
145 Type::I32 => TypeId::of::<i32>(),
146 Type::I64 => TypeId::of::<i64>(),
147 Type::U8 => TypeId::of::<u8>(),
148 Type::U16 => TypeId::of::<u16>(),
149 Type::U32 => TypeId::of::<u32>(),
150 Type::U64 => TypeId::of::<u64>(),
151 Type::F32 => TypeId::of::<f32>(),
152 Type::F64 => TypeId::of::<f64>(),
153 Type::Bool => TypeId::of::<bool>(),
154 Type::String => TypeId::of::<String>(),
155 Type::Datetime => TypeId::of::<String>(),
156 Type::Bytes => TypeId::of::<Vec<u8>>(),
157 Type::Named(_) => TypeId::of::<serde_json::Value>(),
158 Type::List { .. } => TypeId::of::<Vec<Box<dyn std::any::Any>>>(),
159 Type::Optional { .. } => TypeId::of::<Option<Box<dyn std::any::Any>>>(),
160 Type::Map { .. } => TypeId::of::<std::collections::HashMap<Box<dyn std::any::Any>, Box<dyn std::any::Any>>>(),
161 Type::Link { .. } => TypeId::of::<serde_json::Value>(),
162 Type::Object => TypeId::of::<serde_json::Value>(),
163 Type::AnonymousStruct(_) => unimplemented!(),
164 }
165 }
166
167 #[cfg(feature = "value")]
168 pub fn coerce_str<'a>(&self, value: &'a str) -> Result<serde_json::Value, &'a str> {
169 let val = match self {
170 Type::String => serde_json::Value::String(value.to_owned()),
171 Type::U8
172 | Type::U16
173 | Type::U32
174 | Type::U64
175 | Type::I8
176 | Type::I16
177 | Type::I32
178 | Type::I64
179 | Type::F32
180 | Type::F64 => serde_json::Value::Number(value.parse().map_err(|_| value)?),
181 Type::Bool => serde_json::Value::Bool(value.parse().map_err(|_| value)?),
182 Type::Object => match serde_json::from_str(value) {
183 Ok(v) => v,
184 Err(_) => serde_json::from_str(&format!("\"{}\"", value)).map_err(|_| value)?,
185 },
186 Type::List { ty } => {
187 let val: serde_json::Value = serde_json::from_str(value).map_err(|_| value)?;
188 if val.is_array() {
189 val
190 } else {
191 serde_json::Value::Array(vec![ty.coerce_str(value)?])
192 }
193 }
194 Type::Datetime => serde_json::Value::String(value.to_owned()),
195 Type::Bytes => serde_json::Value::String(value.to_owned()),
196 Type::Named(_) => serde_json::Value::Object(serde_json::from_str(value).map_err(|_| value)?),
197 Type::Optional { ty } => {
198 return Ok(ty.coerce_str(value).unwrap_or(serde_json::Value::Null));
199 }
200 Type::Map { .. } => serde_json::from_str(value).map_err(|_| value)?,
201 Type::Link { .. } => unimplemented!(),
202 Type::AnonymousStruct(_) => serde_json::Value::Object(serde_json::from_str(value).map_err(|_| value)?),
203 };
204 Ok(val)
205 }
206}
207
208impl std::fmt::Display for Type {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 match self {
211 Type::I8 => f.write_str("i8"),
212 Type::I16 => f.write_str("i16"),
213 Type::I32 => f.write_str("i32"),
214 Type::I64 => f.write_str("i64"),
215 Type::U8 => f.write_str("u8"),
216 Type::U16 => f.write_str("u16"),
217 Type::U32 => f.write_str("u32"),
218 Type::U64 => f.write_str("u64"),
219 Type::F32 => f.write_str("f32"),
220 Type::F64 => f.write_str("f64"),
221 Type::Bool => f.write_str("bool"),
222 Type::String => f.write_str("string"),
223 Type::Datetime => f.write_str("datetime"),
224 Type::Bytes => f.write_str("bytes"),
225 Type::Named(v) => f.write_str(v),
226 Type::List { ty } => write!(f, "{}[]", ty),
227 Type::Optional { ty } => write!(f, "{}?", ty),
228 Type::Map { key, value } => write!(f, "{{{}:{}}}", key, value),
229 Type::Link { .. } => todo!(),
230 Type::Object => f.write_str("object"),
231 Type::AnonymousStruct(_) => todo!(),
232 }
233 }
234}
235
236#[derive(Debug)]
237pub struct ParseError(String);
239
240impl Error for ParseError {}
241
242impl std::fmt::Display for ParseError {
243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 write!(f, "Could not parse {} into a TypeSignature.", self.0)
245 }
246}
247
248#[cfg(feature = "parser")]
249impl FromStr for Type {
250 type Err = ParseError;
251
252 fn from_str(s: &str) -> Result<Self, Self::Err> {
253 crate::parser::parse(s).map_err(|_e| ParseError(s.to_owned()))
254 }
255}
256
257#[cfg(feature = "parser")]
258pub(crate) fn deserialize_type<'de, D>(deserializer: D) -> Result<Type, D::Error>
259where
260 D: serde::Deserializer<'de>,
261{
262 struct TypeSignatureVisitor;
263
264 impl<'de> serde::de::Visitor<'de> for TypeSignatureVisitor {
265 type Value = Type;
266
267 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
268 formatter.write_str("a TypeSignature definition")
269 }
270
271 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
272 where
273 E: serde::de::Error,
274 {
275 Type::from_str(s).map_err(|e| serde::de::Error::custom(e.to_string()))
276 }
277
278 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
279 where
280 A: serde::de::MapAccess<'de>,
281 {
282 Type::deserialize(serde::de::value::MapAccessDeserializer::new(map))
283 }
284 }
285
286 deserializer.deserialize_any(TypeSignatureVisitor)
287}
288
289#[cfg(feature = "parser")]
290pub(crate) fn box_type_signature<'de, D>(deserializer: D) -> Result<Box<Type>, D::Error>
291where
292 D: serde::Deserializer<'de>,
293{
294 struct TypeVisitor;
295
296 impl<'de> serde::de::Visitor<'de> for TypeVisitor {
297 type Value = Box<Type>;
298
299 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
300 formatter.write_str("a TypeSignature definition")
301 }
302
303 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
304 where
305 E: serde::de::Error,
306 {
307 Type::from_str(s)
308 .map(Box::new)
309 .map_err(|e| serde::de::Error::custom(e.to_string()))
310 }
311
312 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
313 where
314 A: serde::de::MapAccess<'de>,
315 {
316 Type::deserialize(serde::de::value::MapAccessDeserializer::new(map)).map(Box::new)
317 }
318 }
319
320 deserializer.deserialize_any(TypeVisitor)
321}
322
323#[cfg(test)]
324mod test {
325 use anyhow::Result;
326 use serde_json::json;
327
328 use super::{Type as TS, *};
329
330 fn b<T>(el: T) -> Box<T> {
331 Box::new(el)
332 }
333
334 #[test]
335 fn test_decode() -> Result<()> {
336 let ty: Type = serde_json::from_str(r#""object""#)?;
337 assert_eq!(ty, Type::Object);
338 let ty: Field = serde_json::from_str(r#"{"name": "foo", "type": "object"}"#)?;
339 assert_eq!(ty.name, "foo");
340 assert_eq!(ty.ty, Type::Object);
341 Ok(())
342 }
343
344 #[cfg(feature = "value")]
345 #[rstest::rstest]
346 #[case(TS::String, "foo", json!("foo"))]
347 #[case(TS::U32, "48", json!(48))]
348 #[case(TS::List{ty:b(TS::U32)}, "48", json!([48]))]
349 #[case(TS::List{ty:b(TS::String)}, "48", json!(["48"]))]
350 fn test_coerce(#[case] ty: Type, #[case] string: &str, #[case] json: serde_json::Value) -> Result<()> {
351 let val = ty.coerce_str(string).unwrap();
352
353 assert_eq!(val, json);
354 Ok(())
355 }
356}