diff --git a/dar2oar_core/src/condition_parser/conditions.rs b/dar2oar_core/src/condition_parser/conditions.rs index 77602a0..960efb6 100644 --- a/dar2oar_core/src/condition_parser/conditions.rs +++ b/dar2oar_core/src/condition_parser/conditions.rs @@ -193,7 +193,7 @@ mod tests { ConditionSet::IsActorBase(IsActorBase { negated: false, actor_base: PluginValue { - plugin_name: "Skyrim.esm".to_string(), + plugin_name: "Skyrim.esm".into(), form_id: "7".into(), }, ..Default::default() diff --git a/dar2oar_core/src/condition_parser/dar_interface.rs b/dar2oar_core/src/condition_parser/dar_interface.rs index 1127327..2b24222 100644 --- a/dar2oar_core/src/condition_parser/dar_interface.rs +++ b/dar2oar_core/src/condition_parser/dar_interface.rs @@ -72,7 +72,7 @@ impl From<&FnArg<'_>> for NumericValue { form_id, } => Self::GlobalVariable( PluginValue { - plugin_name: plugin_name.to_string(), + plugin_name: (*plugin_name).into(), form_id: NumericLiteral::from(form_id).into(), } .into(), @@ -137,7 +137,7 @@ impl TryFrom> for PluginValue { plugin_name, form_id, } => Ok(Self { - plugin_name: plugin_name.to_string(), + plugin_name: (*plugin_name).into(), form_id: NumericLiteral::from(form_id).into(), }), FnArg::Number(num) => Err(ParseError::UnexpectedValue( @@ -157,7 +157,7 @@ impl TryFrom<&FnArg<'_>> for PluginValue { plugin_name, form_id, } => Ok(Self { - plugin_name: plugin_name.to_string(), + plugin_name: (*plugin_name).into(), form_id: NumericLiteral::from(form_id).into(), }), FnArg::Number(num) => Err(ParseError::UnexpectedValue( @@ -176,7 +176,7 @@ impl From<&FnArg<'_>> for Keyword { form_id, } => Self::Form(FormValue { form: PluginValue { - plugin_name: plugin_name.to_string(), + plugin_name: (*plugin_name).into(), form_id: NumericLiteral::from(form_id).into(), }, }), diff --git a/dar2oar_core/src/conditions/and.rs b/dar2oar_core/src/conditions/and.rs index b3dc20a..8d113f2 100644 --- a/dar2oar_core/src/conditions/and.rs +++ b/dar2oar_core/src/conditions/and.rs @@ -1,4 +1,5 @@ use super::{condition::default_required_version, is_false, ConditionSet}; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; /// - OAR: AND @@ -11,10 +12,10 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct And { /// Condition name "AND" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, diff --git a/dar2oar_core/src/conditions/compare_values.rs b/dar2oar_core/src/conditions/compare_values.rs index 21271f2..276f650 100644 --- a/dar2oar_core/src/conditions/compare_values.rs +++ b/dar2oar_core/src/conditions/compare_values.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::{Cmp, NumericValue}; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct CompareValues { /// Condition name "CompareValues" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -40,12 +41,11 @@ impl Default for CompareValues { #[cfg(test)] mod tests { + use super::*; use crate::values::{ ActorValue, ActorValueType, GraphValue, GraphVariableType, NumericLiteral, NumericValue, PluginValue, StaticValue, }; - - use super::*; use pretty_assertions::assert_eq; #[test] @@ -55,6 +55,7 @@ mod tests { value_b: NumericValue::StaticValue(StaticValue { value: 42.0 }), ..Default::default() }; + let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); let expected = r#"{ "condition": "CompareValues", @@ -67,7 +68,7 @@ mod tests { "value": 42.0 } }"#; - let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); + assert_eq!(serialized, expected); } @@ -85,6 +86,7 @@ mod tests { comparison: Cmp::Ge, ..Default::default() }; + let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); let expected = r#"{ "condition": "CompareValues", @@ -99,7 +101,7 @@ mod tests { "actorValueType": "Max" } }"#; - let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); + assert_eq!(serialized, expected); } @@ -118,6 +120,7 @@ mod tests { comparison: Cmp::Ne, ..Default::default() }; + let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); let expected = r#"{ "condition": "CompareValues", @@ -132,7 +135,7 @@ mod tests { "graphVariableType": "Int" } }"#; - let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); + assert_eq!(serialized, expected); } @@ -141,14 +144,14 @@ mod tests { let compare_values = CompareValues { value_a: NumericValue::GlobalVariable( PluginValue { - plugin_name: "my_plugin.esm".to_string(), + plugin_name: "my_plugin.esm".into(), form_id: 1usize.into(), } .into(), ), value_b: NumericValue::GlobalVariable( PluginValue { - plugin_name: "another_plugin.esp".to_string(), + plugin_name: "another_plugin.esp".into(), form_id: "2".into(), } .into(), @@ -156,6 +159,7 @@ mod tests { comparison: Cmp::Gt, ..Default::default() }; + let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); let expected = r#"{ "condition": "CompareValues", @@ -174,7 +178,7 @@ mod tests { } } }"#; - let serialized = serde_json::to_string_pretty(&compare_values).unwrap(); + assert_eq!(serialized, expected); } } diff --git a/dar2oar_core/src/conditions/condition.rs b/dar2oar_core/src/conditions/condition.rs index fb3fe5c..0c0dcaa 100644 --- a/dar2oar_core/src/conditions/condition.rs +++ b/dar2oar_core/src/conditions/condition.rs @@ -1,21 +1,22 @@ use super::is_false; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; pub const REQUIRED_VERSION: &str = "1.0.0.0"; -pub fn default_required_version() -> String { - REQUIRED_VERSION.to_string() +pub fn default_required_version() -> CompactString { + REQUIRED_VERSION.into() } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Condition { /// Condition name (e.g. IsWornHasKeyword) #[serde(default)] - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] /// The required version for this condition. - pub required_version: String, + pub required_version: CompactString, /// condition to **Not** (default is `false`). #[serde(default)] // NOTE: There is code written under the assumption that it is skipped when false (e.g. IsEquipped). @@ -26,8 +27,8 @@ pub struct Condition { impl Default for Condition { fn default() -> Self { Self { - condition: String::default(), - required_version: REQUIRED_VERSION.to_string(), + condition: CompactString::default(), + required_version: default_required_version(), negated: false, } } @@ -37,7 +38,7 @@ impl Condition { /// Creates a new `Condition` with the specified name. pub fn new(condition: &str) -> Self { Self { - condition: condition.to_string(), + condition: condition.into(), ..Default::default() } } @@ -68,10 +69,11 @@ mod tests { #[test] fn serialize_condition() { let condition = Condition { - condition: "SomeCondition".to_string(), - required_version: REQUIRED_VERSION.to_string(), + condition: "SomeCondition".into(), + required_version: REQUIRED_VERSION.into(), negated: true, }; + let serialized_json = serde_json::to_string_pretty(&condition).unwrap(); let expected_json = r#"{ "condition": "SomeCondition", @@ -79,8 +81,7 @@ mod tests { "negated": true }"#; - let serialized_json = serde_json::to_string_pretty(&condition).unwrap(); - assert_eq!(expected_json, serialized_json); + assert_eq!(serialized_json, expected_json); } #[test] @@ -90,14 +91,14 @@ mod tests { "requiredVersion": "1.0.0.0", "negated": false }"#; + let deserialized: Condition = serde_json::from_str(json_str).unwrap(); - let expected_condition = Condition { - condition: "AnotherCondition".to_string(), - required_version: REQUIRED_VERSION.to_string(), + let expected = Condition { + condition: "AnotherCondition".into(), + required_version: REQUIRED_VERSION.into(), negated: false, }; - let deserialized_condition: Condition = serde_json::from_str(json_str).unwrap(); - assert_eq!(expected_condition, deserialized_condition); + assert_eq!(deserialized, expected); } } diff --git a/dar2oar_core/src/conditions/condition_config.rs b/dar2oar_core/src/conditions/condition_config.rs index 34a72c1..eff7b8d 100644 --- a/dar2oar_core/src/conditions/condition_config.rs +++ b/dar2oar_core/src/conditions/condition_config.rs @@ -1,18 +1,22 @@ use super::ConditionSet; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; /// Each animation root config.json #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] pub struct ConditionsConfig { + /// # NOTE + /// An arbitrary name given by the user (value in the mapping table) will probably exceed 24bytes. + /// Therefore, it should not be a [CompactString]. #[serde(default)] pub name: String, #[serde(default)] - pub description: String, + pub description: CompactString, #[serde(default)] pub priority: i32, #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "overrideAnimationsFolder")] - pub override_animations_folder: Option, + pub override_animations_folder: Option, #[serde(default)] pub conditions: Vec, } diff --git a/dar2oar_core/src/conditions/current_weather.rs b/dar2oar_core/src/conditions/current_weather.rs index 6890419..638ec7d 100644 --- a/dar2oar_core/src/conditions/current_weather.rs +++ b/dar2oar_core/src/conditions/current_weather.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::PluginValue; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct CurrentWeather { /// Condition name "CurrentWeather" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -37,6 +38,7 @@ mod tests { #[test] fn should_serialize_current_weather() { let current_weather = CurrentWeather::default(); + let serialized = serde_json::to_string_pretty(¤t_weather).unwrap(); let expected = r#"{ "condition": "CurrentWeather", @@ -46,8 +48,8 @@ mod tests { "formID": "" } }"#; - let serialized = serde_json::to_string_pretty(¤t_weather).unwrap(); - assert_eq!(expected, serialized); + + assert_eq!(serialized, expected); } #[test] @@ -60,9 +62,10 @@ mod tests { "formID": "" } }"#; + let deserialized: CurrentWeather = serde_json::from_str(json_str).unwrap(); let expected = CurrentWeather::default(); - let deserialized: CurrentWeather = serde_json::from_str(json_str).unwrap(); - assert_eq!(expected, deserialized); + + assert_eq!(deserialized, expected); } } diff --git a/dar2oar_core/src/conditions/faction_rank.rs b/dar2oar_core/src/conditions/faction_rank.rs index 6eb6b56..5adf9ef 100644 --- a/dar2oar_core/src/conditions/faction_rank.rs +++ b/dar2oar_core/src/conditions/faction_rank.rs @@ -1,15 +1,16 @@ use super::{condition::default_required_version, is_false}; use crate::values::{Cmp, NumericValue, PluginValue}; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; /// Tests the ref's faction rank against the specified rank. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct FactionRank { /// Condition name "FactionRank" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -48,13 +49,14 @@ mod tests { fn should_serialize_faction_rank_with_custom_values() { let faction_rank = FactionRank { faction: PluginValue { - plugin_name: "CustomPlugin".to_string(), + plugin_name: "CustomPlugin".into(), form_id: "54321".into(), }, comparison: Cmp::Lt, numeric_value: NumericValue::StaticValue(StaticValue { value: 75.0 }), ..Default::default() }; + let serialized = serde_json::to_string_pretty(&faction_rank).unwrap(); let expected = r#"{ "condition": "FactionRank", @@ -68,8 +70,8 @@ mod tests { "value": 75.0 } }"#; - let serialized = serde_json::to_string_pretty(&faction_rank).unwrap(); - assert_eq!(expected, serialized); + + assert_eq!(serialized, expected); } #[test] @@ -88,11 +90,11 @@ mod tests { } } "#; - let deserialized: FactionRank = serde_json::from_str(json_str).unwrap(); + let expected = FactionRank { faction: PluginValue { - plugin_name: "".to_string(), + plugin_name: "".into(), form_id: "".into(), }, comparison: Cmp::Eq, @@ -100,6 +102,6 @@ mod tests { ..Default::default() }; - assert_eq!(expected, deserialized); + assert_eq!(deserialized, expected); } } diff --git a/dar2oar_core/src/conditions/has_keyword.rs b/dar2oar_core/src/conditions/has_keyword.rs index 0bcd0e4..f23ecde 100644 --- a/dar2oar_core/src/conditions/has_keyword.rs +++ b/dar2oar_core/src/conditions/has_keyword.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::Keyword; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct HasKeyword { /// Condition name "HasKeyword" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -31,14 +32,14 @@ impl Default for HasKeyword { #[cfg(test)] mod tests { - use crate::values::LiteralValue; - use super::*; + use crate::values::LiteralValue; use pretty_assertions::assert_eq; #[test] fn should_serialize_has_keyword() { let has_keyword = HasKeyword::default(); + let serialized = serde_json::to_string_pretty(&has_keyword).unwrap(); let expected = r#"{ "condition": "HasKeyword", @@ -47,8 +48,8 @@ mod tests { "editorID": "" } }"#; - let serialized = serde_json::to_string_pretty(&has_keyword).unwrap(); - assert_eq!(expected, serialized); + + assert_eq!(serialized, expected); } #[test] @@ -60,8 +61,8 @@ mod tests { "editorID": "SomeKeyword" } }"#; - let deserialized: HasKeyword = serde_json::from_str(json_str).unwrap(); + let expected = HasKeyword { keyword: Keyword::Literal(LiteralValue { editor_id: "SomeKeyword".to_string(), @@ -69,6 +70,6 @@ mod tests { ..Default::default() }; - assert_eq!(expected, deserialized); + assert_eq!(deserialized, expected); } } diff --git a/dar2oar_core/src/conditions/has_magic_effect.rs b/dar2oar_core/src/conditions/has_magic_effect.rs index 1739f71..898e85c 100644 --- a/dar2oar_core/src/conditions/has_magic_effect.rs +++ b/dar2oar_core/src/conditions/has_magic_effect.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::PluginValue; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct HasMagicEffect { /// Condition name "HasMagicEffect" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -41,6 +42,7 @@ mod tests { #[test] fn should_serialize_has_magic_effect() { let has_magic_effect = HasMagicEffect::default(); + let serialized = serde_json::to_string_pretty(&has_magic_effect).unwrap(); let expected = r#"{ "condition": "HasMagicEffect", @@ -51,7 +53,7 @@ mod tests { }, "Active effects only": false }"#; - let serialized = serde_json::to_string_pretty(&has_magic_effect).unwrap(); + assert_eq!(serialized, expected); } @@ -66,11 +68,11 @@ mod tests { }, "Active effects only": true }"#; - let deserialized: HasMagicEffect = serde_json::from_str(json_str).unwrap(); + let expected = HasMagicEffect { magic_effect: PluginValue { - plugin_name: "Skyrim.esm".to_string(), + plugin_name: "Skyrim.esm".into(), form_id: "7".into(), // This is player }, active_effects_only: true, diff --git a/dar2oar_core/src/conditions/has_magic_effect_with_keyword.rs b/dar2oar_core/src/conditions/has_magic_effect_with_keyword.rs index 55caa56..846c21e 100644 --- a/dar2oar_core/src/conditions/has_magic_effect_with_keyword.rs +++ b/dar2oar_core/src/conditions/has_magic_effect_with_keyword.rs @@ -1,14 +1,20 @@ use super::{condition::default_required_version, is_false}; use crate::values::{FormValue, Keyword}; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct HasMagicEffectWithKeyword { /// Condition name "HasMagicEffectWithKeyword" + /// + /// # NOTE + /// This condition name is 25bytes. + /// Optimization by [CompactString] is limited to 24bytes, the size of a [String] structure. + /// Therefore, this field cannot be SSO (Small String Optimization). pub condition: String, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -35,14 +41,14 @@ impl Default for HasMagicEffectWithKeyword { #[cfg(test)] mod tests { - use crate::values::PluginValue; - use super::*; + use crate::values::PluginValue; use pretty_assertions::assert_eq; #[test] fn should_serialize_has_magic_effect() { let has_magic_effect = HasMagicEffectWithKeyword::default(); + let serialized = serde_json::to_string_pretty(&has_magic_effect).unwrap(); let expected = r#"{ "condition": "HasMagicEffectWithKeyword", @@ -55,8 +61,8 @@ mod tests { }, "Active effects only": false }"#; - let serialized = serde_json::to_string_pretty(&has_magic_effect).unwrap(); - assert_eq!(expected, serialized); + + assert_eq!(serialized, expected); } #[test] @@ -72,8 +78,8 @@ mod tests { }, "Active effects only": true }"#; - let deserialized: HasMagicEffectWithKeyword = serde_json::from_str(json_str).unwrap(); + let expected = HasMagicEffectWithKeyword { keyword: Keyword::Form(FormValue { form: PluginValue { @@ -85,6 +91,6 @@ mod tests { ..Default::default() }; - assert_eq!(expected, deserialized); + assert_eq!(deserialized, expected); } } diff --git a/dar2oar_core/src/conditions/has_perk.rs b/dar2oar_core/src/conditions/has_perk.rs index 0b7fb76..44ec93f 100644 --- a/dar2oar_core/src/conditions/has_perk.rs +++ b/dar2oar_core/src/conditions/has_perk.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::PluginValue; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct HasPerk { /// Condition name "HasPerk" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -37,6 +38,7 @@ mod tests { #[test] fn should_serialize_has_perk() { let has_perk = HasPerk::default(); + let serialized = serde_json::to_string_pretty(&has_perk).unwrap(); let expected = r#"{ "condition": "HasPerk", @@ -46,7 +48,7 @@ mod tests { "formID": "" } }"#; - let serialized = serde_json::to_string_pretty(&has_perk).unwrap(); + assert_eq!(serialized, expected); } @@ -61,8 +63,8 @@ mod tests { "formID": "12345" } }"#; - let deserialized: HasPerk = serde_json::from_str(json_str).unwrap(); + let expected = HasPerk { negated: true, perk: PluginValue { diff --git a/dar2oar_core/src/conditions/has_ref_type.rs b/dar2oar_core/src/conditions/has_ref_type.rs index 1c0ee7d..5a10d17 100644 --- a/dar2oar_core/src/conditions/has_ref_type.rs +++ b/dar2oar_core/src/conditions/has_ref_type.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::Keyword; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct HasRefType { /// Condition name "HasRefType" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -46,6 +47,7 @@ mod tests { }), ..Default::default() }; + let serialized = serde_json::to_string_pretty(&has_ref_type).unwrap(); let expected = r#"{ "condition": "HasRefType", @@ -57,7 +59,7 @@ mod tests { } } }"#; - let serialized = serde_json::to_string_pretty(&has_ref_type).unwrap(); + assert_eq!(serialized, expected); } @@ -71,8 +73,8 @@ mod tests { "editorID": "ExampleLocationTyp" } }"#; - let deserialized: HasRefType = serde_json::from_str(json_str).unwrap(); + let expected = HasRefType { negated: true, location_ref_type: Keyword::Literal(LiteralValue { diff --git a/dar2oar_core/src/conditions/is_equipped.rs b/dar2oar_core/src/conditions/is_equipped.rs index 1c9c6f9..8c2dafd 100644 --- a/dar2oar_core/src/conditions/is_equipped.rs +++ b/dar2oar_core/src/conditions/is_equipped.rs @@ -1,15 +1,16 @@ use super::{condition::default_required_version, is_false}; use crate::values::PluginValue; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; /// - OAR: IsEquipped #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct IsEquipped { /// Condition name "IsEquipped" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -43,12 +44,13 @@ mod tests { fn should_serialize_is_equipped() { let is_equipped = IsEquipped { form: PluginValue { - plugin_name: "MyPlugin".to_string(), + plugin_name: "MyPlugin".into(), form_id: "12345".into(), }, left_hand: true, ..Default::default() }; + let serialized = serde_json::to_string_pretty(&is_equipped).unwrap(); let expected = r#"{ "condition": "IsEquipped", @@ -59,7 +61,7 @@ mod tests { }, "Left hand": true }"#; - let serialized = serde_json::to_string_pretty(&is_equipped).unwrap(); + assert_eq!(serialized, expected); } @@ -76,13 +78,13 @@ mod tests { }, "Left hand": false }"#; - let deserialized: IsEquipped = serde_json::from_str(json_str).unwrap(); + let expected = IsEquipped { condition: "IsEquipped".into(), negated: true, form: PluginValue { - plugin_name: "Skyrim.esm".to_string(), + plugin_name: "Skyrim.esm".into(), form_id: "7".into(), }, left_hand: false, diff --git a/dar2oar_core/src/conditions/is_equipped_has_keyword.rs b/dar2oar_core/src/conditions/is_equipped_has_keyword.rs index 0504d12..3132f57 100644 --- a/dar2oar_core/src/conditions/is_equipped_has_keyword.rs +++ b/dar2oar_core/src/conditions/is_equipped_has_keyword.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::Keyword; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct IsEquippedHasKeyword { /// Condition name "IsEquippedHasKeyword" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -33,12 +34,55 @@ impl Default for IsEquippedHasKeyword { } } -// { -// "condition": "IsEquippedHasKeyword", -// "requiredVersion": "1.0.0.0", -// "negated": true, -// "Keyword": { -// "editorID": "ExampleKeyword" -// }, -// "Left hand": true -// } +#[cfg(test)] +mod tests { + use super::*; + use crate::values::{FormValue, PluginValue}; + use pretty_assertions::assert_eq; + + #[test] + fn should_serialize_is_equipped_has_keyword() { + let is_equipped_has_keyword = IsEquippedHasKeyword::default(); + let serialized = serde_json::to_string_pretty(&is_equipped_has_keyword).unwrap(); + + let expected = r#"{ + "condition": "IsEquippedHasKeyword", + "requiredVersion": "1.0.0.0", + "Keyword": { + "editorID": "" + }, + "Left hand": false +}"#; + + assert_eq!(serialized, expected); + } + + #[test] + fn should_deserialize_is_equipped_has_keyword() { + let json_str = r#"{ + "condition": "IsEquippedHasKeyword", + "requiredVersion": "1.0.0.0", + "Keyword": { + "form": { + "pluginName": "Skyrim.esm", + "formID": "7" + } + }, + "Left hand": true + }"#; + let deserialized: IsEquippedHasKeyword = serde_json::from_str(json_str).unwrap(); + + let expected = IsEquippedHasKeyword { + keyword: Keyword::Form(FormValue { + form: PluginValue { + plugin_name: "Skyrim.esm".into(), + form_id: "7".into(), + }, + }), + left_hand: true, + ..Default::default() + }; + + assert_eq!(deserialized, expected); + } +} diff --git a/dar2oar_core/src/conditions/is_equipped_type.rs b/dar2oar_core/src/conditions/is_equipped_type.rs index 2f9f286..ec27ca2 100644 --- a/dar2oar_core/src/conditions/is_equipped_type.rs +++ b/dar2oar_core/src/conditions/is_equipped_type.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::TypeValue; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct IsEquippedType { /// Condition name "IsEquippedType" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -48,6 +49,7 @@ mod tests { }, ..Default::default() }; + let serialized = serde_json::to_string_pretty(&is_equipped_type).unwrap(); let expected = r#"{ "condition": "IsEquippedType", @@ -58,7 +60,7 @@ mod tests { }, "Left hand": false }"#; - let serialized = serde_json::to_string_pretty(&is_equipped_type).unwrap(); + assert_eq!(serialized, expected); } @@ -72,8 +74,8 @@ mod tests { }, "Left hand": false }"#; - let deserialized: IsEquippedType = serde_json::from_str(json_str).unwrap(); + let expected = IsEquippedType { type_value: TypeValue { value: WeaponType::IllusionSpell, diff --git a/dar2oar_core/src/conditions/is_movement_direction.rs b/dar2oar_core/src/conditions/is_movement_direction.rs index 6655d96..2f0b0d7 100644 --- a/dar2oar_core/src/conditions/is_movement_direction.rs +++ b/dar2oar_core/src/conditions/is_movement_direction.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::DirectionValue; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct IsMovementDirection { /// Condition name "IsMovementDirection" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -43,6 +44,7 @@ mod tests { }, ..Default::default() }; + let serialized = serde_json::to_string_pretty(&is_movement_direction).unwrap(); let expected = r#"{ "condition": "IsMovementDirection", @@ -51,7 +53,7 @@ mod tests { "value": 4.0 } }"#; - let serialized = serde_json::to_string_pretty(&is_movement_direction).unwrap(); + assert_eq!(serialized, expected); } @@ -66,8 +68,8 @@ mod tests { "value": 2.0 } }"#; - let deserialized: IsMovementDirection = serde_json::from_str(json_str).unwrap(); + let expected = IsMovementDirection { negated: true, direction: DirectionValue { diff --git a/dar2oar_core/src/conditions/is_worn_has_keyword.rs b/dar2oar_core/src/conditions/is_worn_has_keyword.rs index 64eba48..e1b1487 100644 --- a/dar2oar_core/src/conditions/is_worn_has_keyword.rs +++ b/dar2oar_core/src/conditions/is_worn_has_keyword.rs @@ -1,14 +1,15 @@ use super::{condition::default_required_version, is_false}; use crate::values::Keyword; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct IsWornHasKeyword { /// Condition name "IsWornHasKeyword" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -28,3 +29,53 @@ impl Default for IsWornHasKeyword { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::values::{FormValue, PluginValue}; + use pretty_assertions::assert_eq; + + #[test] + fn should_serialize_is_worn_has_keyword() { + let is_worn_has_keyword = IsWornHasKeyword::default(); + let serialized = serde_json::to_string_pretty(&is_worn_has_keyword).unwrap(); + + let expected = r#"{ + "condition": "IsWornHasKeyword", + "requiredVersion": "1.0.0.0", + "Keyword": { + "editorID": "" + } +}"#; + + assert_eq!(serialized, expected); + } + + #[test] + fn should_deserialize_is_worn_has_keyword() { + let json_str = r#"{ + "condition": "IsWornHasKeyword", + "requiredVersion": "1.0.0.0", + "Keyword": { + "form": { + "pluginName": "Skyrim.esm", + "formID": "7" + } + } + }"#; + let deserialized: IsWornHasKeyword = serde_json::from_str(json_str).unwrap(); + + let expected = IsWornHasKeyword { + keyword: Keyword::Form(FormValue { + form: PluginValue { + plugin_name: "Skyrim.esm".into(), + form_id: "7".into(), + }, + }), + ..Default::default() + }; + + assert_eq!(deserialized, expected); + } +} diff --git a/dar2oar_core/src/conditions/mod.rs b/dar2oar_core/src/conditions/mod.rs index 3482cfa..f61451c 100644 --- a/dar2oar_core/src/conditions/mod.rs +++ b/dar2oar_core/src/conditions/mod.rs @@ -31,6 +31,7 @@ pub use self::{ use self::condition::default_required_version; use crate::values::{Cmp, NumericValue, PluginValue}; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[inline] @@ -45,10 +46,10 @@ macro_rules! gen_cmp_num_struct { $(#[$attr])* #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct $name { - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, @@ -94,10 +95,10 @@ macro_rules! gen_one_plugin_struct { $(#[$attr])* #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct $name { - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, diff --git a/dar2oar_core/src/conditions/or.rs b/dar2oar_core/src/conditions/or.rs index 3b76122..00ed230 100644 --- a/dar2oar_core/src/conditions/or.rs +++ b/dar2oar_core/src/conditions/or.rs @@ -1,4 +1,5 @@ use super::{condition::default_required_version, is_false, ConditionSet}; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; /// - OAR: OR @@ -6,10 +7,10 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Or { /// Condition name "OR" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, diff --git a/dar2oar_core/src/conditions/random.rs b/dar2oar_core/src/conditions/random.rs index 8a5e68d..522ac9b 100644 --- a/dar2oar_core/src/conditions/random.rs +++ b/dar2oar_core/src/conditions/random.rs @@ -1,15 +1,16 @@ use super::{condition::default_required_version, is_false}; use crate::values::{Cmp, NumericValue, RandomValue}; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; /// - OAR: Random #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RandomCondition { /// Condition name "Random" - pub condition: String, + pub condition: CompactString, #[serde(default = "default_required_version")] #[serde(rename = "requiredVersion")] - pub required_version: String, + pub required_version: CompactString, #[serde(default)] #[serde(skip_serializing_if = "is_false")] pub negated: bool, diff --git a/dar2oar_core/src/fs/converter/common.rs b/dar2oar_core/src/fs/converter/common.rs index 4ba9155..a2a6ec0 100644 --- a/dar2oar_core/src/fs/converter/common.rs +++ b/dar2oar_core/src/fs/converter/common.rs @@ -88,10 +88,10 @@ where let section_name = match is_1st_person { true => section_1person_table .as_ref() - .and_then(|table| table.get(&priority_str)), + .and_then(|table| table.get(priority_str.as_str())), false => section_table .as_ref() - .and_then(|table| table.get(&priority_str)), + .and_then(|table| table.get(priority_str.as_str())), } .unwrap_or(&priority_str); diff --git a/dar2oar_core/src/fs/converter/mod.rs b/dar2oar_core/src/fs/converter/mod.rs index c72b238..c01a272 100644 --- a/dar2oar_core/src/fs/converter/mod.rs +++ b/dar2oar_core/src/fs/converter/mod.rs @@ -5,6 +5,7 @@ pub mod sequential; pub mod support_cmd; use crate::error::Result; +use compact_str::CompactString; use std::collections::HashMap; /// # Convert DAR to OAR @@ -106,9 +107,9 @@ pub struct ConvertOptions { /// mod author in config.json pub author: Option, /// path to section name table - pub section_table: Option>, + pub section_table: Option>, /// path to section name table(For _1st_person) - pub section_1person_table: Option>, + pub section_1person_table: Option>, /// use multi thread(Probably effective for those with long DAR syntax. Basically single-threaded is faster.) pub run_parallel: bool, /// After converting to OAR, add mohidden to the DAR directory before conversion to treat it as a hidden directory. (for MO2 users) @@ -134,7 +135,7 @@ mod test { // oar_dir: Some(OAR_DIR.into()), // cannot use include_str! // section_table: Some(crate::read_mapping_table(TABLE_PATH).await?), - run_parallel: true, + // run_parallel: true, // hide_dar: true, ..Default::default() }) @@ -171,7 +172,7 @@ mod test { } } - let _guard = handle.await.unwrap(); + handle.await??; Ok(()) } } diff --git a/dar2oar_core/src/fs/converter/sequential.rs b/dar2oar_core/src/fs/converter/sequential.rs index a18d39a..aa9dd00 100644 --- a/dar2oar_core/src/fs/converter/sequential.rs +++ b/dar2oar_core/src/fs/converter/sequential.rs @@ -41,7 +41,6 @@ pub async fn convert_dar_to_oar( tracing::debug!("[Start {}th conversion]\n{:?}", idx, &parsed_path); convert_inner(&options, path, &parsed_path, &is_converted_once).await?; - progress_fn(idx); tracing::debug!("[End {}th conversion]\n\n", idx); idx += 1; diff --git a/dar2oar_core/src/fs/mapping_table.rs b/dar2oar_core/src/fs/mapping_table.rs index c0e84fd..d1cdc1c 100644 --- a/dar2oar_core/src/fs/mapping_table.rs +++ b/dar2oar_core/src/fs/mapping_table.rs @@ -1,4 +1,5 @@ use crate::error::{ConvertError, Result}; +use compact_str::CompactString; use std::collections::HashMap; use std::path::Path; use tokio::{fs::File, io::AsyncReadExt}; @@ -6,7 +7,7 @@ use tokio::{fs::File, io::AsyncReadExt}; /// Get mapping table from path pub async fn get_mapping_table( mapping_path: Option>, -) -> Option> { +) -> Option> { match mapping_path { Some(table_path) => read_mapping_table(table_path).await.ok(), None => None, @@ -14,7 +15,9 @@ pub async fn get_mapping_table( } /// Try to read mapping table from path -pub async fn read_mapping_table(table_path: impl AsRef) -> Result> { +pub async fn read_mapping_table( + table_path: impl AsRef, +) -> Result> { let table_path = table_path.as_ref(); if !table_path.exists() { return Err(ConvertError::NonExistPath(format!("{table_path:?}"))); @@ -28,7 +31,9 @@ pub async fn read_mapping_table(table_path: impl AsRef) -> Result HashMap { +/// The key can only be up to [f32]::MAX due to DAR specifications. +/// Therefore, [CompactString] is used to fit into 24 bytes. +fn parse_mapping_table(table: &str) -> HashMap { let mut map = HashMap::new(); // Sequential numbering of duplicate keys when no key is available. @@ -92,13 +97,13 @@ mod tests { let result = parse_mapping_table(input); let mut expected = HashMap::new(); - expected.insert("8000000".into(), "Combat".to_string()); - expected.insert("8000001".into(), "Base".to_string()); - expected.insert("8000002".into(), "Base_1".to_string()); - expected.insert("8000005".into(), "Female".to_string()); - expected.insert("8001000".into(), "Unarmed".to_string()); - expected.insert("8001010".into(), "Sword".to_string()); - expected.insert("8001020".into(), "Sword+Shield".to_string()); + expected.insert("8000000".into(), "Combat".into()); + expected.insert("8000001".into(), "Base".into()); + expected.insert("8000002".into(), "Base_1".into()); + expected.insert("8000005".into(), "Female".into()); + expected.insert("8001000".into(), "Unarmed".into()); + expected.insert("8001010".into(), "Sword".into()); + expected.insert("8001020".into(), "Sword+Shield".into()); assert_eq!(result, expected); } diff --git a/dar2oar_core/src/values/keyword_value.rs b/dar2oar_core/src/values/keyword_value.rs index 392a500..bfd5a9c 100644 --- a/dar2oar_core/src/values/keyword_value.rs +++ b/dar2oar_core/src/values/keyword_value.rs @@ -106,7 +106,7 @@ mod tests { let deserialized: Keyword = serde_json::from_str(input).unwrap(); let expected = Keyword::Form(FormValue { form: PluginValue { - plugin_name: "MyPlugin".to_string(), + plugin_name: "MyPlugin".into(), form_id: "12345".into(), }, }); diff --git a/dar2oar_core/src/values/plugin_value.rs b/dar2oar_core/src/values/plugin_value.rs index e22f731..60172f9 100644 --- a/dar2oar_core/src/values/plugin_value.rs +++ b/dar2oar_core/src/values/plugin_value.rs @@ -1,4 +1,5 @@ use super::NumericLiteral; +use compact_str::CompactString; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] @@ -27,13 +28,13 @@ pub struct PluginValue { /// Non prefix(0x) hexadecimal ID #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct FormID(String); +pub struct FormID(CompactString); impl From<&str> for FormID { /// Clone into /// - NOTE: non cast to hex fn from(value: &str) -> Self { - Self(value.to_owned()) + Self(value.into()) } } @@ -54,19 +55,15 @@ from!(usize, isize, f32); impl From for FormID { fn from(value: NumericLiteral) -> Self { Self(match value { - NumericLiteral::Hex(hex_value) => { - format!("{:x}", hex_value) - } + NumericLiteral::Hex(hex_value) => format!("{:x}", hex_value).into(), NumericLiteral::Decimal(decimal_value) => { if decimal_value == 0 { - String::default() + CompactString::default() } else { - format!("{:x}", decimal_value) + format!("{:x}", decimal_value).into() } } - NumericLiteral::Float(float_value) => { - format!("{:x}", float_value as usize) - } + NumericLiteral::Float(float_value) => format!("{:x}", float_value as usize).into(), }) } }