1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
use serde::de::Error; use serde_yaml::Mapping; use serde_yaml::Value; use crate::dsl::schema::object_types::bounds::deserialization::deserialize_array_object_bounds; use crate::dsl::schema::object_types::bounds::deserialization::deserialize_default_value; use crate::dsl::schema::object_types::bounds::deserialization::deserialize_integer_bounds; use crate::dsl::schema::object_types::bounds::deserialization::deserialize_string_object_bounds; use crate::dsl::schema::object_types::bounds::IntegerValueConditionObjectBounds; use crate::dsl::schema::object_types::bounds::IntegerObjectBounds; use crate::dsl::schema::object_types::ObjectType; use crate::dsl::schema::object_types::RawObjectType; use crate::dsl::schema::object_types::bounds::deserialization::deserialize_integer_bounds_with_defaults; use crate::dsl::schema::object_types::bounds::IntegerBound; use crate::dsl::schema::object_types::ObjectTypeData; pub fn deserialize_object_type<E>(mapping: &Mapping) -> Result<Option<Vec<ObjectType>>, E> where E: Error, { let type_key = Value::from("type"); Ok(mapping.get(&type_key).map_or(Ok(None), |value| match value { Value::String(string) => Ok(Some(vec![deserialize_individual_type_definition(string, &mapping)?])), Value::Sequence(sequence) => Ok(Some(deserialize_array_of_types(sequence, mapping)?)), _ => Err(Error::custom(format!( "cannot recognize type definition format `{:#?}`", value ))), })?) } fn deserialize_array_of_types<E>(sequence: &[Value], mapping: &Mapping) -> Result<Vec<ObjectType>, E> where E: Error, { sequence .iter() .map(|type_definition| match type_definition { Value::String(string) => Ok(deserialize_individual_type_definition(string, mapping)?), _ => Err(Error::custom("type definition needs to be a string")), }) .collect() } fn deserialize_individual_type_definition<E>(definition: &str, mapping: &Mapping) -> Result<ObjectType, E> where E: Error, { let mut type_name = definition.trim().to_lowercase(); let default_value = deserialize_default_value(mapping)?; Ok(if type_name.ends_with('?') { type_name.remove(type_name.len() - 1); let raw_type = RawObjectType::from(&type_name, &mapping)?; let type_data = ObjectTypeData::with_raw_type_and_default_value(raw_type, default_value); ObjectType::Optional(type_data) } else { let raw_type = RawObjectType::from(&type_name, &mapping)?; let type_data = ObjectTypeData::with_raw_type_and_default_value(raw_type, default_value); ObjectType::Required(type_data) }) } pub fn deserialize_integer<E>(name: &str, mapping: &Mapping) -> Result<Option<i64>, E> where E: Error, { let value = mapping.get(&Value::from(name)); value.map_or(Ok(None), |value| { Ok(Some(value.as_i64().ok_or_else(|| { Error::custom(format!("cannot deserialize {:#?} as integer", value)) })?)) }) } impl RawObjectType { fn from<E>(value: &str, mapping: &Mapping) -> Result<Self, E> where E: Error, { let object_type = match value { "object" => RawObjectType::Object, "string" => RawObjectType::String(deserialize_string_object_bounds(mapping)?), "text" => RawObjectType::Text(deserialize_string_object_bounds(mapping)?), "integer" => RawObjectType::Integer(deserialize_integer_bounds(mapping)?), "number" => RawObjectType::Number(deserialize_integer_bounds(mapping)?), "port" => { let defaults = IntegerValueConditionObjectBounds { minimum: Some(IntegerBound::Inclusive(0)), maximum: Some(IntegerBound::Inclusive(65535)), multiple_of: None, }; let defaults = IntegerObjectBounds::Conditions(defaults); RawObjectType::Port(Some(deserialize_integer_bounds_with_defaults(defaults, mapping)?)) } "password" => RawObjectType::Password(deserialize_string_object_bounds(mapping)?), "boolean" => RawObjectType::Boolean, "array" => RawObjectType::Array(Box::new(deserialize_array_object_bounds(mapping)?)), "stringlist" => RawObjectType::Stringlist(Box::new(deserialize_array_object_bounds(mapping)?)), "hostname" => RawObjectType::Hostname, "datetime" => RawObjectType::Datetime, "date" => RawObjectType::Date, "time" => RawObjectType::Time, "email" => RawObjectType::Email, "ipv4" => RawObjectType::IPV4, "ipv6" => RawObjectType::IPV6, "uri" => RawObjectType::URI, "file" => RawObjectType::File, _ => RawObjectType::Text(deserialize_string_object_bounds(mapping)?), }; Ok(object_type) } }