Refactor YAML code

This commit is contained in:
Oliver Hamlet
2025-03-25 22:02:34 +00:00
parent fdaed322df
commit d6781f6a32
13 changed files with 108 additions and 126 deletions
+1 -1
View File
@@ -7,11 +7,11 @@ use super::{
MessageContent, emit_message_contents, parse_message_contents_yaml,
validate_message_contents,
},
yaml::{EmitYaml, YamlEmitter},
yaml::{
YamlObjectType, as_string_node, get_required_string_value, get_string_value,
parse_condition,
},
yaml_emit::{EmitYaml, YamlEmitter},
};
/// Represents a file in a game's Data folder, including files in
+1 -5
View File
@@ -1,10 +1,10 @@
use saphyr::MarkedYaml;
use super::error::ParseMetadataError;
use super::yaml::{EmitYaml, YamlEmitter};
use super::yaml::{
YamlObjectType, get_as_hash, get_required_string_value, get_string_value, get_strings_vec_value,
};
use super::yaml_emit::{EmitYaml, YamlEmitter};
/// Represents a group to which plugin metadata objects can belong.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
@@ -104,10 +104,6 @@ impl TryFrom<&MarkedYaml> for Group {
}
impl EmitYaml for Group {
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter) {
emitter.begin_map();
+2 -2
View File
@@ -3,9 +3,9 @@ use saphyr::{MarkedYaml, YamlData};
use super::error::ExpectedType;
use super::error::ParseMetadataError;
use super::yaml::EmitYaml;
use super::yaml::YamlEmitter;
use super::yaml::{YamlObjectType, get_required_string_value};
use super::yaml_emit::EmitYaml;
use super::yaml_emit::YamlEmitter;
/// Represents a URL at which the parent plugin can be found.
#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
+1 -9
View File
@@ -10,11 +10,11 @@ use super::{
ExpectedType, MetadataParsingErrorReason, MultilingualMessageContentsError,
ParseMetadataError,
},
yaml::{EmitYaml, YamlEmitter},
yaml::{
YamlObjectType, as_string_node, get_as_hash, get_required_string_value,
get_strings_vec_value, parse_condition,
},
yaml_emit::{EmitYaml, YamlEmitter},
};
/// Codes used to indicate the type of a message.
@@ -388,10 +388,6 @@ impl TryFrom<&MarkedYaml> for Message {
}
impl EmitYaml for MessageContent {
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter) {
emitter.begin_map();
@@ -425,10 +421,6 @@ pub(super) fn emit_message_contents(
}
impl EmitYaml for Message {
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter) {
emitter.begin_map();
+2 -71
View File
@@ -1,7 +1,6 @@
use std::{
collections::{HashMap, HashSet},
path::Path,
sync::LazyLock,
};
use saphyr::{MarkedYaml, YamlData};
@@ -11,18 +10,15 @@ use crate::logging;
use super::{
error::{
ExpectedType, LoadMetadataError, MetadataDocumentParsingError, ParseMetadataError,
RegexError, WriteMetadataError, YamlMergeKeyError,
RegexError, WriteMetadataError,
},
file::Filename,
group::Group,
message::Message,
plugin_metadata::PluginMetadata,
yaml::{YamlObjectType, as_string_node, get_as_slice},
yaml_emit::{EmitYaml, YamlEmitter},
yaml::{EmitYaml, YamlEmitter, YamlObjectType, get_as_slice, process_merge_keys},
};
static MERGE_KEY: LazyLock<MarkedYaml> = LazyLock::new(|| as_string_node("<<"));
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MetadataDocument {
bash_tags: Vec<String>,
@@ -342,71 +338,6 @@ impl std::default::Default for MetadataDocument {
}
}
fn process_merge_keys(mut yaml: MarkedYaml) -> Result<MarkedYaml, YamlMergeKeyError> {
match yaml.data {
YamlData::Array(a) => {
yaml.data = merge_array_elements(a).map(YamlData::Array)?;
Ok(yaml)
}
YamlData::Hash(h) => {
yaml.data = merge_hash_keys(h).map(YamlData::Hash)?;
Ok(yaml)
}
_ => Ok(yaml),
}
}
fn merge_array_elements(
array: saphyr::AnnotatedArray<MarkedYaml>,
) -> Result<saphyr::AnnotatedArray<MarkedYaml>, YamlMergeKeyError> {
array.into_iter().map(process_merge_keys).collect()
}
fn merge_hash_keys(
hash: saphyr::AnnotatedHash<MarkedYaml>,
) -> Result<saphyr::AnnotatedHash<MarkedYaml>, YamlMergeKeyError> {
let mut hash: saphyr::AnnotatedHash<MarkedYaml> = hash
.into_iter()
.map(|(key, value)| {
process_merge_keys(key)
.and_then(|key| process_merge_keys(value).map(|value| (key, value)))
})
.collect::<Result<_, _>>()?;
if let Some(value) = hash.remove(&MERGE_KEY) {
merge_into_hash(hash, value)
} else {
Ok(hash)
}
}
fn merge_into_hash(
hash: saphyr::AnnotatedHash<MarkedYaml>,
value: MarkedYaml,
) -> Result<saphyr::AnnotatedHash<MarkedYaml>, YamlMergeKeyError> {
match value.data {
YamlData::<MarkedYaml>::Array(a) => a.into_iter().try_fold(hash, |acc, e| {
if let YamlData::Hash(h) = e.data {
Ok(merge_hashes(acc, h))
} else {
Err(YamlMergeKeyError::new(e))
}
}),
YamlData::<MarkedYaml>::Hash(h) => Ok(merge_hashes(hash, h)),
_ => Err(YamlMergeKeyError::new(value)),
}
}
fn merge_hashes(
mut hash1: saphyr::AnnotatedHash<MarkedYaml>,
hash2: saphyr::AnnotatedHash<MarkedYaml>,
) -> saphyr::AnnotatedHash<MarkedYaml> {
for (key, value) in hash2 {
hash1.entry(key).or_insert(value);
}
hash1
}
fn replace_prelude(masterlist: String, prelude: String) -> String {
let line_ending = detect_line_ending(&masterlist);
if let Some((start, end)) = find_prelude_bounds(&masterlist) {
+2 -3
View File
@@ -9,7 +9,6 @@ mod plugin_cleaning_data;
pub(crate) mod plugin_metadata;
mod tag;
mod yaml;
mod yaml_emit;
pub use file::{File, Filename};
pub use group::Group;
@@ -20,8 +19,8 @@ pub use plugin_metadata::PluginMetadata;
pub use tag::{Tag, TagSuggestion};
#[cfg(test)]
fn emit<T: yaml_emit::EmitYaml>(metadata: &T) -> String {
let mut emitter = yaml_emit::YamlEmitter::new();
fn emit<T: yaml::EmitYaml>(metadata: &T) -> String {
let mut emitter = yaml::YamlEmitter::new();
metadata.emit_yaml(&mut emitter);
emitter.into_string()
+1 -5
View File
@@ -6,8 +6,8 @@ use super::{
MessageContent, emit_message_contents, parse_message_contents_yaml,
validate_message_contents,
},
yaml::{EmitYaml, YamlEmitter},
yaml::{YamlObjectType, as_string_node, get_as_hash, get_required_string_value, get_u32_value},
yaml_emit::{EmitYaml, YamlEmitter},
};
/// Represents data identifying the plugin under which it is stored as dirty or
@@ -181,10 +181,6 @@ impl TryFrom<&MarkedYaml> for PluginCleaningData {
}
impl EmitYaml for PluginCleaningData {
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter) {
emitter.begin_map();
+1 -5
View File
@@ -12,10 +12,10 @@ use super::{
message::Message,
plugin_cleaning_data::PluginCleaningData,
tag::Tag,
yaml::{EmitYaml, YamlEmitter},
yaml::{
YamlObjectType, get_as_hash, get_as_slice, get_required_string_value, get_string_value,
},
yaml_emit::{EmitYaml, YamlEmitter},
};
pub(crate) const GHOST_FILE_EXTENSION: &str = ".ghost";
@@ -376,10 +376,6 @@ fn get_vec<'a, T: TryFrom<&'a MarkedYaml, Error = impl Into<ParseMetadataError>>
}
impl EmitYaml for PluginMetadata {
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter) {
emitter.begin_map();
+2 -2
View File
@@ -2,9 +2,9 @@ use saphyr::YamlData;
use super::error::ExpectedType;
use super::error::ParseMetadataError;
use super::yaml::EmitYaml;
use super::yaml::YamlEmitter;
use super::yaml::{YamlObjectType, get_required_string_value, parse_condition};
use super::yaml_emit::EmitYaml;
use super::yaml_emit::YamlEmitter;
/// Represents whether a Bash Tag suggestion is for addition or removal.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
@@ -1,5 +1,7 @@
pub trait EmitYaml {
fn is_scalar(&self) -> bool;
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter);
}
@@ -277,10 +279,6 @@ fn double_quote(value: &str) -> String {
}
impl<T: EmitYaml> EmitYaml for &[T] {
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter) {
match self {
[] => {}
@@ -305,10 +303,6 @@ impl<T: EmitYaml> EmitYaml for &[T] {
}
impl<T: EmitYaml> EmitYaml for Vec<T> {
fn is_scalar(&self) -> bool {
false
}
fn emit_yaml(&self, emitter: &mut YamlEmitter) {
self.as_slice().emit_yaml(emitter);
}
+74
View File
@@ -0,0 +1,74 @@
use std::sync::LazyLock;
use saphyr::{MarkedYaml, YamlData};
use crate::metadata::error::YamlMergeKeyError;
use super::as_string_node;
static MERGE_KEY: LazyLock<MarkedYaml> = LazyLock::new(|| as_string_node("<<"));
pub fn process_merge_keys(mut yaml: MarkedYaml) -> Result<MarkedYaml, YamlMergeKeyError> {
match yaml.data {
YamlData::Array(a) => {
yaml.data = merge_array_elements(a).map(YamlData::Array)?;
Ok(yaml)
}
YamlData::Hash(h) => {
yaml.data = merge_hash_keys(h).map(YamlData::Hash)?;
Ok(yaml)
}
_ => Ok(yaml),
}
}
fn merge_array_elements(
array: saphyr::AnnotatedArray<MarkedYaml>,
) -> Result<saphyr::AnnotatedArray<MarkedYaml>, YamlMergeKeyError> {
array.into_iter().map(process_merge_keys).collect()
}
fn merge_hash_keys(
hash: saphyr::AnnotatedHash<MarkedYaml>,
) -> Result<saphyr::AnnotatedHash<MarkedYaml>, YamlMergeKeyError> {
let mut hash: saphyr::AnnotatedHash<MarkedYaml> = hash
.into_iter()
.map(|(key, value)| {
process_merge_keys(key)
.and_then(|key| process_merge_keys(value).map(|value| (key, value)))
})
.collect::<Result<_, _>>()?;
if let Some(value) = hash.remove(&MERGE_KEY) {
merge_into_hash(hash, value)
} else {
Ok(hash)
}
}
fn merge_into_hash(
hash: saphyr::AnnotatedHash<MarkedYaml>,
value: MarkedYaml,
) -> Result<saphyr::AnnotatedHash<MarkedYaml>, YamlMergeKeyError> {
match value.data {
YamlData::<MarkedYaml>::Array(a) => a.into_iter().try_fold(hash, |acc, e| {
if let YamlData::Hash(h) = e.data {
Ok(merge_hashes(acc, h))
} else {
Err(YamlMergeKeyError::new(e))
}
}),
YamlData::<MarkedYaml>::Hash(h) => Ok(merge_hashes(hash, h)),
_ => Err(YamlMergeKeyError::new(value)),
}
}
fn merge_hashes(
mut hash1: saphyr::AnnotatedHash<MarkedYaml>,
hash2: saphyr::AnnotatedHash<MarkedYaml>,
) -> saphyr::AnnotatedHash<MarkedYaml> {
for (key, value) in hash2 {
hash1.entry(key).or_insert(value);
}
hash1
}
+10
View File
@@ -0,0 +1,10 @@
mod emit;
mod merge;
mod parse;
pub use emit::{EmitYaml, YamlEmitter};
pub use merge::process_merge_keys;
pub use parse::{
YamlObjectType, as_string_node, get_as_hash, get_as_slice, get_required_string_value,
get_string_value, get_strings_vec_value, get_u32_value, parse_condition, to_yaml,
};
@@ -1,9 +1,9 @@
use std::str::FromStr;
use loot_condition_interpreter::Expression;
use saphyr::{AnnotatedArray, AnnotatedHash, MarkedYaml, Marker, Yaml, YamlData};
use saphyr::{AnnotatedHash, MarkedYaml, Marker, Yaml, YamlData};
use super::error::{ExpectedType, MetadataParsingErrorReason, ParseMetadataError};
use super::super::error::{ExpectedType, MetadataParsingErrorReason, ParseMetadataError};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum YamlObjectType {
@@ -42,24 +42,18 @@ pub fn to_yaml(yaml: &MarkedYaml) -> Yaml {
saphyr::YamlData::Integer(v) => Yaml::Integer(*v),
saphyr::YamlData::String(v) => Yaml::String(v.clone()),
saphyr::YamlData::Boolean(v) => Yaml::Boolean(*v),
saphyr::YamlData::Array(v) => Yaml::Array(to_array(v)),
saphyr::YamlData::Hash(v) => Yaml::Hash(to_hash(v)),
saphyr::YamlData::Array(v) => Yaml::Array(v.iter().map(to_yaml).collect()),
saphyr::YamlData::Hash(v) => Yaml::Hash(
v.iter()
.map(|(key, value)| (to_yaml(key), to_yaml(value)))
.collect(),
),
saphyr::YamlData::Alias(v) => Yaml::Alias(*v),
saphyr::YamlData::Null => Yaml::Null,
saphyr::YamlData::BadValue => Yaml::BadValue,
}
}
fn to_array(array: &AnnotatedArray<MarkedYaml>) -> saphyr::Array {
array.iter().map(to_yaml).collect()
}
fn to_hash(hash: &AnnotatedHash<MarkedYaml>) -> saphyr::Hash {
hash.iter()
.map(|(key, value)| (to_yaml(key), to_yaml(value)))
.collect()
}
pub fn as_string_node(value: &str) -> MarkedYaml {
MarkedYaml {
span: saphyr_parser::Span::default(),