diff --git a/Cargo.lock b/Cargo.lock index ca2e229..0da2b58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -794,7 +794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -832,6 +832,7 @@ dependencies = [ "nom", "pretty_assertions", "serde", + "serde-untagged", "serde_json", "temp-dir", "thiserror", @@ -863,7 +864,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -874,7 +875,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -1003,6 +1004,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "erased-serde" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55d05712b2d8d88102bc9868020c9e5c7a1f5527c452b9b97450a1d006140ba7" +dependencies = [ + "serde", +] + [[package]] name = "errno" version = "0.3.3" @@ -1217,7 +1227,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -2606,9 +2616,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -2624,9 +2634,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2933,22 +2943,32 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-untagged" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a160535368dfc353348e7eaa299156bd508c60c45a9249725f5f6d370d82a66" +dependencies = [ + "erased-serde", + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -2970,7 +2990,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -3008,7 +3028,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -3194,9 +3214,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" dependencies = [ "proc-macro2", "quote", @@ -3576,7 +3596,7 @@ checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -3663,7 +3683,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -3750,7 +3770,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", ] [[package]] @@ -3948,7 +3968,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", "wasm-bindgen-shared", ] @@ -3982,7 +4002,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.49", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/dar2oar_core/Cargo.toml b/dar2oar_core/Cargo.toml index 333f7e0..4cc11ce 100644 --- a/dar2oar_core/Cargo.toml +++ b/dar2oar_core/Cargo.toml @@ -19,6 +19,7 @@ compact_str = { version = "0.7.1", features = ["serde"] } jwalk = "0.8.1" # To parallel traverse dir recursivly nom = { version = "7.1.3", features = ["alloc"] } # Syntax serde = { version = "1.0", features = ["derive"] } # Implement (De)Serializer +serde-untagged = "0.1" serde_json = "1.0" # Json converter thiserror = "1.0.48" # define errors type tokio = { version = "1.33.0", features = [ diff --git a/dar2oar_core/src/condition_parser/dar_interface.rs b/dar2oar_core/src/condition_parser/dar_interface.rs index 965cb82..f705434 100644 --- a/dar2oar_core/src/condition_parser/dar_interface.rs +++ b/dar2oar_core/src/condition_parser/dar_interface.rs @@ -183,13 +183,13 @@ impl TryFrom<&FnArg<'_>> for Direction { fn try_from(value: &FnArg<'_>) -> Result { match value { FnArg::Number(num) => Ok(match *num { - NumberLiteral::Hex(num) => (num as u64) + NumberLiteral::Hex(num) => (num as f64) .try_into() .map_err(|e: &str| ParseError::UnexpectedValue(e.into(), "0..=4".into()))?, - NumberLiteral::Decimal(num) => (num as u64) + NumberLiteral::Decimal(num) => (num as f64) .try_into() .map_err(|e: &str| ParseError::UnexpectedValue(e.into(), "0..=4".into()))?, - NumberLiteral::Float(num) => (num as u64) + NumberLiteral::Float(num) => (num as f64) .try_into() .map_err(|e: &str| ParseError::UnexpectedValue(e.into(), "0..=4".into()))?, }), diff --git a/dar2oar_core/src/values/actor_value.rs b/dar2oar_core/src/values/actor_value.rs index 91db7a8..aeedc6b 100644 --- a/dar2oar_core/src/values/actor_value.rs +++ b/dar2oar_core/src/values/actor_value.rs @@ -25,10 +25,11 @@ pub struct ActorValue { /// - Actor Value Percentage (0-1) => "Percentage" /// /// default: `ActorValue` -#[derive(Debug, Clone, Default, PartialEq, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum ActorValueType { /// Value #[default] + #[serde(rename = "Value")] ActorValue, /// Base Base, @@ -38,80 +39,12 @@ pub enum ActorValueType { Percentage, } -impl TryFrom<&str> for ActorValueType { - type Error = &'static str; - - fn try_from(value: &str) -> Result { - Ok(match value { - "Value" => Self::ActorValue, - "Base" => Self::Base, - "Max" => Self::Max, - "Percentage" => Self::Percentage, - _ => return Err("Invalid actor value type"), - }) - } -} - -impl From for &str { - fn from(value: ActorValueType) -> Self { - match value { - ActorValueType::ActorValue => "Value", - ActorValueType::Base => "Base", - ActorValueType::Max => "Max", - ActorValueType::Percentage => "Percentage", - } - } -} - -impl Serialize for ActorValueType { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(self.clone().into()) - } -} - -impl<'de> Deserialize<'de> for ActorValueType { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let type_str = String::deserialize(deserializer)?; - type_str - .as_str() - .try_into() - .map_err(serde::de::Error::custom) - } -} - #[cfg(test)] mod tests { use super::*; use anyhow::Result; use pretty_assertions::assert_eq; - #[test] - fn test_try_from_str_valid() { - let value = "Value"; - let result = ActorValueType::try_from(value); - assert_eq!(result, Ok(ActorValueType::ActorValue)); - } - - #[test] - fn test_try_from_str_invalid() { - let value = "InvalidValue"; - let result = ActorValueType::try_from(value); - assert_eq!(result, Err("Invalid actor value type")); - } - - #[test] - fn test_into_str() { - let value = ActorValueType::Base; - let result: &str = value.into(); - assert_eq!(result, "Base"); - } - #[test] fn test_serialize() -> Result<()> { let value = ActorValueType::Max; diff --git a/dar2oar_core/src/values/comparison.rs b/dar2oar_core/src/values/comparison.rs index 616d043..8cd0f3b 100644 --- a/dar2oar_core/src/values/comparison.rs +++ b/dar2oar_core/src/values/comparison.rs @@ -1,6 +1,5 @@ //! Comparison -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::fmt; +use serde::{Deserialize, Serialize}; /// Comparison /// - Eq: Equal("==") <- default @@ -9,89 +8,25 @@ use std::fmt; /// - Lt: Less than("<") /// - Ge: Greater than or equal(">=") /// - Le: Lesser than or equal("<="), -#[derive(Debug, Clone, Default, PartialEq, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum Cmp { + #[serde(rename = "==")] #[default] /// Equal("==") Eq, + #[serde(rename = "!=")] /// Not Equal("!=") Ne, + #[serde(rename = ">")] /// Greater than(">") Gt, + #[serde(rename = "<")] /// Less than("<") Lt, + #[serde(rename = ">=")] /// Greater than or equal(">=") Ge, + #[serde(rename = "<=")] /// Lesser than or equal("<=") Le, } - -// Implement Display trait for pretty printing -impl fmt::Display for Cmp { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Self::Eq => write!(f, "=="), - Self::Ne => write!(f, "!="), - Self::Gt => write!(f, ">"), - Self::Lt => write!(f, "<"), - Self::Ge => write!(f, ">="), - Self::Le => write!(f, "<="), - } - } -} - -// Implement TryFrom<&str> to parse from a string -impl TryFrom<&str> for Cmp { - type Error = &'static str; - - fn try_from(value: &str) -> Result { - Ok(match value { - "==" => Self::Eq, - "!=" => Self::Ne, - ">" => Self::Gt, - "<" => Self::Lt, - ">=" => Self::Ge, - "<=" => Self::Le, - _ => { - return Err( - "Invalid comparison operator. Expected '==', '!=', '>', '<', '>=' or '<='", - ) - } - }) - } -} - -impl From for &str { - fn from(value: Cmp) -> Self { - match value { - Cmp::Eq => "==", - Cmp::Ne => "!=", - Cmp::Gt => ">", - Cmp::Lt => "<", - Cmp::Ge => ">=", - Cmp::Le => "<=", - } - } -} - -impl Serialize for Cmp { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(self.clone().into()) - } -} - -impl<'de> Deserialize<'de> for Cmp { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let cmp_str = String::deserialize(deserializer)?; - cmp_str - .as_str() - .try_into() - .map_err(serde::de::Error::custom) - } -} diff --git a/dar2oar_core/src/values/direction_value.rs b/dar2oar_core/src/values/direction_value.rs index b1e6c73..b9c5a22 100644 --- a/dar2oar_core/src/values/direction_value.rs +++ b/dar2oar_core/src/values/direction_value.rs @@ -1,7 +1,7 @@ //! Actor's Direction -use serde::de::{Error, Unexpected, Visitor}; +use serde::de::Unexpected; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde_json::Value; +use serde_untagged::UntaggedEnumVisitor; /// Actor's Direction #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] @@ -26,16 +26,16 @@ pub enum Direction { Left, } -impl TryFrom for Direction { +impl TryFrom for Direction { type Error = &'static str; - fn try_from(value: u64) -> Result { + fn try_from(value: f64) -> Result { Ok(match value { - 0 => Self::None, - 1 => Self::Forward, - 2 => Self::Right, - 3 => Self::Back, - 4 => Self::Left, + x if (0.0..1.0).contains(&x) => Self::None, + x if (1.0..2.0).contains(&x) => Self::Forward, + x if (2.0..3.0).contains(&x) => Self::Right, + x if (3.0..4.0).contains(&x) => Self::Back, + x if (4.0..5.0).contains(&x) => Self::Left, _ => return Err("Invalid value for Direction"), }) } @@ -71,58 +71,13 @@ impl<'de> Deserialize<'de> for Direction { where D: Deserializer<'de>, { - /// Inner struct for deserialization - struct DirectionVisitor; - - impl<'de> Visitor<'de> for DirectionVisitor { - type Value = Direction; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a valid Direction value") - } - - fn visit_u64(self, value: u64) -> Result - where - E: Error, - { - Direction::try_from(value).map_or_else( - |_err| { - Err(Error::unknown_variant( - &value.to_string(), - &["0", "1", "2", "3", "4"], - )) - }, - |value| Ok(value), - ) - } - } - - // Deserialize from a JSON value. - let value: Value = Deserialize::deserialize(deserializer)?; - match value { - Value::Number(num) => { - let err = || { - Error::invalid_type(Unexpected::Other("WeaponType parse f64"), &"a valid f64") - }; - let direction = num.as_u64().unwrap_or(num.as_f64().ok_or_else(err)? as u64); - let err = |err| Error::invalid_type(Unexpected::Other(err), &"a valid u64 or f64"); - let direction = Self::try_from(direction).map_err(err)?; - Ok(direction) - } - Value::String(s) => { - let t = s.parse::().map_err(|_err| { - Error::invalid_type( - Unexpected::Other("Couldn't parse float value"), - &"a valid Direction value", - ) - })?; - DirectionVisitor.visit_f64(t) - } - _ => Err(Error::invalid_type( - Unexpected::Other("not a valid value for Direction"), - &"a valid Direction value", - )), - } + UntaggedEnumVisitor::new() + .f64(|float| { + float.try_into().map_err(|_err| { + serde::de::Error::invalid_value(Unexpected::Float(float), &r#"0.0..=4.0"#) + }) + }) + .deserialize(deserializer) } } @@ -137,11 +92,11 @@ mod tests { let direction_value = DirectionValue { value: Direction::Back, }; + let serialized = serde_json::to_string_pretty(&direction_value)?; let expected = r#"{ "value": 3.0 }"#; - let serialized = serde_json::to_string_pretty(&direction_value)?; assert_eq!(serialized, expected); Ok(()) } diff --git a/dar2oar_core/src/values/graph_value.rs b/dar2oar_core/src/values/graph_value.rs index 98ce5bb..fbe2a06 100644 --- a/dar2oar_core/src/values/graph_value.rs +++ b/dar2oar_core/src/values/graph_value.rs @@ -1,5 +1,5 @@ //! Pair str & Int | Float | Bool -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Serialize}; /// Pair str & Int | Float | Bool #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] @@ -15,7 +15,7 @@ pub struct GraphValue { } /// Float | Int | Bool -#[derive(Debug, Clone, Default, PartialEq, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum GraphVariableType { /// Floating point number #[default] @@ -26,35 +26,6 @@ pub enum GraphVariableType { Bool, } -impl Serialize for GraphVariableType { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let type_str = match self { - Self::Float => "Float", - Self::Int => "Int", - Self::Bool => "Bool", - }; - serializer.serialize_str(type_str) - } -} - -impl<'de> Deserialize<'de> for GraphVariableType { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let type_str = String::deserialize(deserializer)?; - Ok(match type_str.as_str() { - "Float" => Self::Float, - "Int" => Self::Int, - "Bool" => Self::Bool, - _ => return Err(serde::de::Error::custom("Invalid graph variable type")), - }) - } -} - #[cfg(test)] mod tests { use super::*; @@ -62,7 +33,7 @@ mod tests { use pretty_assertions::assert_eq; #[test] - fn should_serialize_current_weather() -> Result<()> { + fn should_serialize_graph_value() -> Result<()> { let graph_value = GraphValue::default(); let expected = r#"{ @@ -73,4 +44,21 @@ mod tests { assert_eq!(serialized, expected); Ok(()) } + + #[test] + fn should_deserialize_graph_value() -> Result<()> { + let actual = r#"{ + "graphVariable": "", + "graphVariableType": "Int" +}"#; + let actual: GraphValue = serde_json::from_str(actual)?; + + let expected = GraphValue { + graph_variable: "".into(), + graph_variable_type: GraphVariableType::Int, + }; + + assert_eq!(actual, expected); + Ok(()) + } } diff --git a/dar2oar_core/src/values/type_value.rs b/dar2oar_core/src/values/type_value.rs index 15b2d33..1329fb3 100644 --- a/dar2oar_core/src/values/type_value.rs +++ b/dar2oar_core/src/values/type_value.rs @@ -1,7 +1,6 @@ //! Wrapper for [`WeaponType`] -use serde::de::{Error, Visitor}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde_json::Value; +use serde_untagged::UntaggedEnumVisitor; use super::NumericLiteral; @@ -101,37 +100,37 @@ impl TryFrom for WeaponType { -1..=18 => Ok((num as i64).try_into()?), _ => Err("Got Decimal, Out of range -1..=18"), }, - NumericLiteral::Float(num) => Ok(num.to_string().as_str().try_into()?), + NumericLiteral::Float(num) => Ok(num.try_into()?), } } } -impl TryFrom<&str> for WeaponType { +impl TryFrom for WeaponType { type Error = &'static str; - fn try_from(value: &str) -> Result { - Ok(match value { - "-1" | "-1.0" => Self::Other, - "0" | "0.0" => Self::Unarmed, - "1" | "1.0" => Self::Sword, - "2" | "2.0" => Self::Dagger, - "3" | "3.0" => Self::WarAxe, - "4" | "4.0" => Self::Mace, - "5" | "5.0" => Self::Greatsword, - "6" | "6.0" => Self::Battleaxe, - "7" | "7.0" => Self::Bow, - "8" | "8.0" => Self::Staff, - "9" | "9.0" => Self::Crossbow, - "10" | "10.0" => Self::Warhammer, - "11" | "11.0" => Self::Shield, - "12" | "12.0" => Self::AlterationSpell, - "13" | "13.0" => Self::IllusionSpell, - "14" | "14.0" => Self::DestructionSpell, - "15" | "15.0" => Self::ConjurationSpell, - "16" | "16.0" => Self::RestorationSpell, - "17" | "17.0" => Self::Scroll, - "18" | "18.0" => Self::Torch, - _ => return Err("Invalid value for WeaponType"), + fn try_from(float: f32) -> Result { + Ok(match float { + x if (-1.0..0.0).contains(&x) => Self::Other, + x if (0.0..1.0).contains(&x) => Self::Unarmed, + x if (1.0..2.0).contains(&x) => Self::Sword, + x if (2.0..3.0).contains(&x) => Self::Dagger, + x if (3.0..4.0).contains(&x) => Self::WarAxe, + x if (4.0..5.0).contains(&x) => Self::Mace, + x if (5.0..6.0).contains(&x) => Self::Greatsword, + x if (6.0..7.0).contains(&x) => Self::Battleaxe, + x if (7.0..8.0).contains(&x) => Self::Bow, + x if (8.0..9.0).contains(&x) => Self::Staff, + x if (9.0..10.0).contains(&x) => Self::Crossbow, + x if (10.0..11.0).contains(&x) => Self::Warhammer, + x if (11.0..12.0).contains(&x) => Self::Shield, + x if (12.0..13.0).contains(&x) => Self::AlterationSpell, + x if (13.0..14.0).contains(&x) => Self::IllusionSpell, + x if (14.0..15.0).contains(&x) => Self::DestructionSpell, + x if (15.0..16.0).contains(&x) => Self::ConjurationSpell, + x if (16.0..17.0).contains(&x) => Self::RestorationSpell, + x if (17.0..18.0).contains(&x) => Self::Scroll, + x if (18.0..19.0).contains(&x) => Self::Torch, + _ => return Err("Expected -1.0..=18.0"), }) } } @@ -181,61 +180,24 @@ impl<'de> Deserialize<'de> for WeaponType { where D: Deserializer<'de>, { - /// Inner struct to deserialization. - struct WeaponTypeVisitor; - - impl<'de> Visitor<'de> for WeaponTypeVisitor { - type Value = WeaponType; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a valid WeaponType value") - } - - fn visit_f64(self, value: f64) -> Result - where - E: Error, - { - WeaponType::try_from(value as i64).or(Err(Error::unknown_variant( - &value.to_string(), - &[ - "-1.0", "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0", "8.0", - "9.0", "10.0", "11.0", "12.0", "13.0", "14.0", "15.0", "16.0", "17.0", - "18.0", - ], - ))) - } - } - - // Deserialize from a JSON value. - let value: Value = Deserialize::deserialize(deserializer)?; - match value { - Value::Number(num) => { - let weapon = - Self::try_from(num.as_i64().unwrap_or(num.as_f64().ok_or_else(|| { - Error::invalid_type( - serde::de::Unexpected::Other("WeaponType parse f64"), - &"a valid f64", - ) - })? as i64)) - .map_err(|err| { - Error::invalid_type( - serde::de::Unexpected::Other(err), - &"a valid i64 or f64", - ) - })?; - Ok(weapon) - } - Value::String(s) => Ok(s.as_str().try_into().map_err(|_err| { - Error::invalid_type( - serde::de::Unexpected::Other("Couldn't parse float value"), - &"a valid WeaponType float string", - ) - })?), - _ => Err(Error::invalid_type( - serde::de::Unexpected::Other("not a valid value for WeaponType"), - &"a valid WeaponType value", - )), - } + UntaggedEnumVisitor::new() + .f32(|float| { + float.try_into().map_err(|_err| { + serde::de::Error::invalid_value( + serde::de::Unexpected::Float(float.into()), + &r#"-1.0..=18.0"#, + ) + }) + }) + .f64(|float| { + (float as f32).try_into().map_err(|_err| { + serde::de::Error::invalid_value( + serde::de::Unexpected::Float(float), + &r#"-1.0..=18.0"#, + ) + }) + }) + .deserialize(deserializer) } } @@ -275,9 +237,9 @@ mod tests { } #[test] - fn should_deserialize_type_value_as_string() -> Result<()> { + fn should_deserialize_type_value2() -> Result<()> { let json_str = r#"{ - "value": "5.0" + "value": 5.0 }"#; let deserialized: TypeValue = serde_json::from_str(json_str)?;