Skip to content

Commit

Permalink
stringtables: preserve comments (#827)
Browse files Browse the repository at this point in the history
  • Loading branch information
BrettMayson authored Nov 9, 2024
1 parent f5ddcd5 commit 829c241
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 14 deletions.
16 changes: 14 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion libs/stringtable/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ hemtt-workspace = { path = "../workspace", version = "1.0.0" }
automod = { workspace = true }
linkme = { workspace = true }
paste = { workspace = true }
quick-xml = { version = "0.36.2", features = ["serialize"] }
quick-xml = { version = "0.37.0", features = ["serialize"] }
serde = { workspace = true, features = ["derive"] }
serde-aux = "4.5.0"
toml = { workspace = true }
tracing = { workspace = true }

Expand Down
76 changes: 65 additions & 11 deletions libs/stringtable/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::io::BufReader;

use quick_xml::se::Serializer;
use serde::{Deserialize, Serialize};

Expand All @@ -9,13 +11,17 @@ mod totals;
pub use key::Key;
pub use package::Package;
pub use totals::Totals;
use tracing::error;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Project {
#[serde(rename = "@name")]
name: String,
#[serde(rename = "Package")]
packages: Vec<Package>,

#[serde(skip)]
meta_comments: Vec<(String, String)>,
}

impl Project {
Expand All @@ -39,28 +45,76 @@ impl Project {
/// Read a Project from a reader
///
/// # Errors
/// [`quick_xml::de::DeError`] if the reader is not a valid stringtable
/// [`quick_xml::DeError`] if the reader is not a valid stringtable
pub fn from_reader<R: std::io::BufRead>(reader: R) -> Result<Self, quick_xml::de::DeError> {
quick_xml::de::from_reader(reader)
let mut buffer = String::new();
let mut reading_comments = false;
let mut comments = Vec::new();
let Ok(reader) = reader
.lines()
.map(|l| {
let Ok(l) = l else {
error!("Failed to read line: {:?}", l);
return l;
};
if !reading_comments && !buffer.is_empty() {
comments.push((buffer.trim().to_string(), l.trim().to_string()));
buffer.clear();
}
if l.trim().starts_with("<!--") {
reading_comments = true;
}
if reading_comments {
buffer.push_str(&l);
if l.trim().ends_with("-->") {
reading_comments = false;
}
}
Ok(l)
})
.collect::<Result<Vec<_>, _>>()
else {
return Err(quick_xml::de::DeError::Custom(
"Failed to read lines".to_string(),
));
};
comments.sort();
comments.dedup();
let mut this: Self =
quick_xml::de::from_reader(BufReader::new(reader.join("\n").as_bytes()))?;
this.meta_comments = comments;
Ok(this)
}

/// Write a Project to a writer
///
/// # Errors
/// [`quick_xml::ser::Error`] if the writer fails to write
pub fn to_writer<W: std::fmt::Write>(
&self,
writer: &mut W,
) -> Result<(), quick_xml::de::DeError> {
// If this write fails, the serializer will also throw an error
let _ = writer.write_str(r#"<?xml version="1.0" encoding="utf-8"?>"#);
let _ = writer.write_char('\n');
/// [`quick_xml::SeError`] if the writer fails to write
pub fn to_writer<W: std::fmt::Write>(&self, writer: &mut W) -> Result<(), quick_xml::SeError> {
writer.write_str(r#"<?xml version="1.0" encoding="utf-8"?>"#)?;
writer.write_char('\n')?;
let mut buffer = String::new();
let mut ser = Serializer::new(&mut buffer);
ser.indent(' ', 4);
self.serialize(ser)?;
buffer.push('\n');
writer.write_str(&buffer)?;

for line in buffer.lines() {
for (before, after) in &self.meta_comments {
if line.trim().starts_with(after) {
let whitespace = line
.chars()
.take_while(|c| c.is_whitespace())
.collect::<String>();
writer.write_str(&whitespace)?;
writer.write_str(before)?;
writer.write_char('\n')?;
}
}
writer.write_str(line)?;
writer.write_char('\n')?;
}

Ok(())
}
}
1 change: 1 addition & 0 deletions libs/stringtable/tests/snapshots/ace_arsenal__sort-2.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6127,4 +6127,5 @@ Project {
containers: [],
},
],
meta_comments: [],
}
1 change: 1 addition & 0 deletions libs/stringtable/tests/snapshots/ace_arsenal__sort.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6127,4 +6127,5 @@ Project {
containers: [],
},
],
meta_comments: [],
}

0 comments on commit 829c241

Please sign in to comment.