use serde::{Deserialize, Serialize};
use serde_json::Number;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(untagged)]
pub enum Literal {
String(String),
Number(Number),
Boolean(bool),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct TypeLiteral {
pub value: Literal,
pub description: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(tag = "complex_type", rename_all = "snake_case")]
pub enum Type {
Array {
value: Box<Type>,
},
Dictionary {
key: Box<Type>,
value: Box<Type>,
},
Tuple {
values: Vec<Type>,
},
Union {
options: Vec<Type>,
full_format: bool,
},
Literal(TypeLiteral),
Type {
value: Box<Type>,
description: String,
},
Struct,
#[serde(untagged)]
Simple(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn complex_type_array() {
let json = r#"
{
"complex_type": "array",
"value": "foo"
}"#;
let expected = Type::Array {
value: Box::new(Type::Simple("foo".into())),
};
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(actual, expected);
}
#[test]
fn complex_type_dictionary() {
let json = r#"
{
"complex_type": "dictionary",
"key": "AirbornePollutantID",
"value": "double"
}"#;
let expected = Type::Dictionary {
key: Box::new(Type::Simple("AirbornePollutantID".into())),
value: Box::new(Type::Simple("double".into())),
};
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(actual, expected);
}
#[test]
fn complex_type_tuple() {
let json = r#"
{
"complex_type": "tuple",
"values": [
"Vector",
"Vector",
"Vector",
"Vector"
]
}"#;
let expected = Type::Tuple {
values: vec![
Type::Simple("Vector".into()),
Type::Simple("Vector".into()),
Type::Simple("Vector".into()),
Type::Simple("Vector".into()),
],
};
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(actual, expected);
}
#[test]
fn complex_type_union() {
let json = r#"
{
"complex_type": "union",
"options": [
{
"complex_type": "literal",
"value": "game-finished"
},
{
"complex_type": "literal",
"value": "rocket-launched"
}
],
"full_format": false
}"#;
let expected = Type::Union {
options: vec![
Type::Literal(TypeLiteral {
value: Literal::String("game-finished".into()),
description: None,
}),
Type::Literal(TypeLiteral {
value: Literal::String("rocket-launched".into()),
description: None,
}),
],
full_format: false,
};
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(actual, expected);
}
#[test]
fn complex_type_literal_string() {
let json = r#"
{
"complex_type": "literal",
"value": "foo"
}"#;
let expected = Type::Literal(TypeLiteral {
value: Literal::String("foo".into()),
description: None,
});
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(actual, expected);
}
#[test]
fn complex_type_literal_number() {
let json = r#"
{
"complex_type": "literal",
"value": 1
}"#;
let expected = Type::Literal(TypeLiteral {
value: Literal::Number(1.into()),
description: None,
});
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn complex_type_literal_bool() {
let json = r#"
{
"complex_type": "literal",
"value": true
}"#;
let expected = Type::Literal(TypeLiteral {
value: Literal::Boolean(true),
description: None,
});
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn complex_type_literal_description() {
let json = r#"
{
"complex_type": "literal",
"value": true,
"description": "foo"
}"#;
let expected = Type::Literal(TypeLiteral {
value: Literal::Boolean(true),
description: Some("foo".into()),
});
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn complex_type_type() {
let json = r#"
{
"complex_type": "type",
"value": "AccumulatorPrototype",
"description": "`'accumulator'`"
}"#;
let expected = Type::Type {
value: Box::new(Type::Simple("AccumulatorPrototype".into())),
description: "`'accumulator'`".into(),
};
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(actual, expected);
}
#[test]
fn complex_type_struct() {
let json = r#"
{
"complex_type": "struct"
}"#;
let expected = Type::Struct;
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(actual, expected);
}
#[test]
fn simple() {
let json = r#""foo""#;
let expected = Type::Simple("foo".into());
let actual = serde_json::from_str::<Type>(json).unwrap();
assert_eq!(expected, actual);
}
}