mod derive { use arma_rs::{FromArma, FromArmaError, IntoArma, Value}; fn sort_value_array(value: &mut Value) -> &Value { if let Value::Array(values) = value { values.sort_by(|a, b| a.partial_cmp(b).unwrap()); } value } #[derive(Debug, PartialEq, Default)] enum ValueStringImpl { #[default] Even, Odd, } impl std::fmt::Display for ValueStringImpl { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Even => write!(f, "even"), Self::Odd => write!(f, "odd"), } } } impl std::str::FromStr for ValueStringImpl { type Err = String; fn from_str(s: &str) -> Result { match s.chars().count() % 2 { 0 => Ok(Self::Even), _ => Ok(Self::Odd), } } } #[test] #[cfg(not(miri))] fn compile() { let tests = trybuild::TestCases::new(); tests.compile_fail("tests/derive/*fail*.rs"); tests.pass("tests/derive/*pass*.rs"); } mod map { use super::*; #[test] fn derive() { #[derive(FromArma, IntoArma, Debug, PartialEq)] struct DeriveTest { first: String, second: bool, } let serialized = DeriveTest { first: "first".to_string(), second: true, }; let deserialized = Value::Array(vec![ Value::Array(vec![ Value::String("first".to_string()), Value::String("first".to_string()), ]), Value::Array(vec![ Value::String("second".to_string()), Value::Boolean(true), ]), ]); assert_eq!(sort_value_array(&mut serialized.to_arma()), &deserialized); assert_eq!( DeriveTest::from_arma(deserialized.to_string()), Ok(serialized) ); } #[test] fn transparent() { #[derive(FromArma, IntoArma, Debug, PartialEq)] #[arma(transparent)] struct DeriveTest { expected: String, } let serialized = DeriveTest { expected: "expected".to_string(), }; let deserialized = Value::String("expected".to_string()); assert_eq!(serialized.to_arma(), deserialized); assert_eq!( DeriveTest::from_arma(deserialized.to_string()), Ok(serialized) ); } #[test] fn from_str_field() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest { #[arma(from_str)] expected: ValueStringImpl, } let input = Value::Array(vec![Value::Array(vec![ Value::String("expected".to_string()), Value::String("odd".to_string()), ])]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { expected: ValueStringImpl::Odd, }) ); } #[test] fn to_string_field() { #[derive(IntoArma, Debug, PartialEq)] struct DeriveTest { #[arma(to_string)] expected: ValueStringImpl, } assert_eq!( DeriveTest { expected: ValueStringImpl::Odd, } .to_arma(), Value::Array(vec![Value::Array(vec![ Value::String("expected".to_string()), Value::String("odd".to_string()), ])]) ); } #[test] fn from_str_default_field() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest { #[arma(from_str, default)] expected: ValueStringImpl, } let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { expected: ValueStringImpl::default(), }) ); } #[test] fn default() { #[derive(FromArma, Default, Debug, PartialEq)] #[arma(default)] struct DeriveTest { first: String, second: bool, } let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest::default()) ); let input = Value::Array(vec![Value::Array(vec![ Value::String("first".to_string()), Value::String("first".to_string()), ])]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { first: "first".to_string(), ..DeriveTest::default() }) ); let input = Value::Array(vec![Value::Array(vec![ Value::String("second".to_string()), Value::Boolean(true), ])]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { second: true, ..DeriveTest::default() }) ); let input = Value::Array(vec![ Value::Array(vec![ Value::String("first".to_string()), Value::String("first".to_string()), ]), Value::Array(vec![ Value::String("second".to_string()), Value::Boolean(true), ]), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { first: "first".to_string(), second: true }) ); } #[test] fn default_field() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest { first: String, #[arma(default)] second: bool, } let input = Value::Array(vec![Value::Array(vec![ Value::String("first".to_string()), Value::String("first".to_string()), ])]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { first: "first".to_string(), second: false }) ); let input = Value::Array(vec![ Value::Array(vec![ Value::String("first".to_string()), Value::String("first".to_string()), ]), Value::Array(vec![ Value::String("second".to_string()), Value::Boolean(true), ]), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { first: "first".to_string(), second: true }) ); } #[test] fn default_field_precedence() { #[derive(FromArma, Debug, PartialEq)] #[arma(default)] struct DeriveTest { first: String, #[arma(default)] second: bool, } impl Default for DeriveTest { fn default() -> Self { Self { first: "first".to_string(), second: true, } } } let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest { first: "first".to_string(), second: false }) ); } #[test] fn error_missing() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest { _expected: String, } let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Err(FromArmaError::MissingField("_expected".to_string())) ); } #[test] fn error_unknown() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest { _expected: String, } let input = Value::Array(vec![ Value::Array(vec![ Value::String("_expected".to_string()), Value::String("_expected".to_string()), ]), Value::Array(vec![ Value::String("unknown".to_string()), Value::String("unknown".to_string()), ]), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Err(FromArmaError::UnknownField("unknown".to_string())) ); } #[test] fn error_duplicate() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest { _expected: String, } let input = Value::Array(vec![ Value::Array(vec![ Value::String("_expected".to_string()), Value::String("first".to_string()), ]), Value::Array(vec![ Value::String("_expected".to_string()), Value::String("second".to_string()), ]), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Err(FromArmaError::DuplicateField("_expected".to_string())) ); } #[test] fn default_error_unknown() { #[derive(FromArma, Default, Debug, PartialEq)] #[arma(default)] struct DeriveTest { _expected: String, } let input = Value::Array(vec![Value::Array(vec![ Value::String("unknown".to_string()), Value::String("unknown".to_string()), ])]); assert_eq!( DeriveTest::from_arma(input.to_string()), Err(FromArmaError::UnknownField("unknown".to_string())) ); } #[test] fn default_field_error_missing() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest { _expected: String, #[arma(default)] _default: String, } let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Err(FromArmaError::MissingField("_expected".to_string())) ); } } mod tuple { use super::*; #[test] fn derive() { #[derive(FromArma, IntoArma, Debug, PartialEq)] struct DeriveTest(String, bool); let serialized = DeriveTest("first".to_string(), true); let deserialized = Value::Array(vec![ Value::String("first".to_string()), Value::Boolean(true), ]); assert_eq!(serialized.to_arma(), deserialized); assert_eq!( DeriveTest::from_arma(deserialized.to_string()), Ok(serialized) ); } #[test] fn from_string_field() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest(String, #[arma(from_str)] ValueStringImpl); let input = Value::Array(vec![ Value::String("first".to_string()), Value::String("odd".to_string()), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), ValueStringImpl::Odd)) ); } #[test] fn to_string_field() { #[derive(IntoArma, Debug, PartialEq)] struct DeriveTest(String, #[arma(to_string)] ValueStringImpl); assert_eq!( DeriveTest("first".to_string(), ValueStringImpl::Odd).to_arma(), Value::Array(vec![ Value::String("first".to_string()), Value::String("odd".to_string()), ]) ); } #[test] fn from_str_default_field() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest(String, #[arma(from_str, default)] ValueStringImpl); let input = Value::Array(vec![Value::String("first".to_string())]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), ValueStringImpl::default())) ); } #[test] fn default() { #[derive(FromArma, Default, Debug, PartialEq)] #[arma(default)] struct DeriveTest(String, bool); let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest::default()) ); let input = Value::Array(vec![Value::String("first".to_string())]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), false)) ); let input = Value::Array(vec![ Value::String("first".to_string()), Value::Boolean(true), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), true)) ); } #[test] fn default_field() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest(String, #[arma(default)] bool); let input = Value::Array(vec![Value::String("first".to_string())]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), false)) ); let input = Value::Array(vec![ Value::String("first".to_string()), Value::Boolean(true), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), true)) ); } #[test] fn default_multi_field() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest(String, #[arma(default)] bool, #[arma(default)] bool); let input = Value::Array(vec![Value::String("first".to_string())]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), false, false)) ); let input = Value::Array(vec![ Value::String("first".to_string()), Value::Boolean(true), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), true, false)) ); let input = Value::Array(vec![ Value::String("first".to_string()), Value::Boolean(true), Value::Boolean(true), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), true, true)) ); } #[test] fn default_field_precedence() { #[derive(FromArma, Debug, PartialEq)] #[arma(default)] struct DeriveTest(String, #[arma(default)] bool); impl Default for DeriveTest { fn default() -> Self { Self("first".to_string(), true) } } let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest("first".to_string(), false)) ); } #[test] fn error_length() { #[derive(FromArma, Default, Debug, PartialEq)] struct DeriveTest(String, String); let input = Value::Array(vec![ Value::String("first".to_string()), Value::String("second".to_string()), Value::String("third".to_string()), Value::String("forth".to_string()), ]); assert_eq!( DeriveTest::from_arma(input.to_string()), Err(arma_rs::FromArmaError::InvalidLength { expected: 2, actual: 4, }) ); } #[test] fn default_field_error() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest(String, #[arma(default)] String); let input = Value::Array(vec![]); assert_eq!( DeriveTest::from_arma(input.to_string()), Err(arma_rs::FromArmaError::InvalidLength { expected: 2, actual: 0, }) ); } } mod newtype { use super::*; #[test] fn derive() { #[derive(FromArma, IntoArma, Debug, PartialEq)] struct DeriveTest(String); let serialized = DeriveTest("expected".to_string()); let deserialized = Value::String("expected".to_string()); assert_eq!(serialized.to_arma(), deserialized); assert_eq!( DeriveTest::from_arma(deserialized.to_string()), Ok(serialized) ); } #[test] fn from_str() { #[derive(FromArma, Debug, PartialEq)] struct DeriveTest(#[arma(from_str)] ValueStringImpl); let input = Value::String("odd".to_string()); assert_eq!( DeriveTest::from_arma(input.to_string()), Ok(DeriveTest(ValueStringImpl::Odd)) ); } #[test] fn to_string() { #[derive(IntoArma, Debug, PartialEq)] struct DeriveTest(#[arma(to_string)] ValueStringImpl); assert_eq!( DeriveTest(ValueStringImpl::Odd).to_arma(), Value::String("odd".to_string()), ); } } }