diff options
Diffstat (limited to 'server/common/src/grit.rs')
| -rw-r--r-- | server/common/src/grit.rs | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/server/common/src/grit.rs b/server/common/src/grit.rs index ee96500..9d01dac 100644 --- a/server/common/src/grit.rs +++ b/server/common/src/grit.rs @@ -4,7 +4,7 @@ use anyhow::Error; use std::collections::VecDeque; use std::fs; use std::io::{BufReader, Read}; -use std::path::Path; +use std::path::{Path, PathBuf}; use tokio::task::spawn_blocking; use xml::attribute::OwnedAttribute; use xml::reader::{EventReader, ParserConfig, XmlEvent}; @@ -1018,9 +1018,16 @@ fn parse_grit_part_element<R: Read>( pub async fn parse_grit(path: impl AsRef<Path>) -> anyhow::Result<Grit> { let path = path.as_ref().to_path_buf(); + parse_grit_with_opener(move || Ok(BufReader::new(fs::File::open(path)?))).await +} + +pub async fn parse_grit_with_opener<F, R>(opener: F) -> anyhow::Result<Grit> +where + F: FnOnce() -> anyhow::Result<BufReader<R>> + Send + 'static, + R: Read, +{ spawn_blocking(move || { - let file = fs::File::open(path)?; - let reader = BufReader::new(file); + let reader = opener()?; let mut ereader = ParserConfig::new() .ignore_comments(true) .whitespace_to_characters(true) @@ -1064,9 +1071,16 @@ pub async fn parse_grit(path: impl AsRef<Path>) -> anyhow::Result<Grit> { pub async fn parse_grit_part(path: impl AsRef<Path>) -> anyhow::Result<GritPart> { let path = path.as_ref().to_path_buf(); + parse_grit_part_with_opener(|| Ok(BufReader::new(fs::File::open(path)?))).await +} + +pub async fn parse_grit_part_with_opener<F, R>(opener: F) -> anyhow::Result<GritPart> +where + F: FnOnce() -> anyhow::Result<BufReader<R>> + Send + 'static, + R: Read, +{ spawn_blocking(move || { - let file = fs::File::open(path)?; - let reader = BufReader::new(file); + let reader = opener()?; let mut ereader = ParserConfig::new() .ignore_comments(true) .whitespace_to_characters(true) @@ -1121,20 +1135,20 @@ fn if_message_to_if_message_part(messages: Vec<IfMessage>) -> Vec<IfMessagePart> .collect() } -async fn maybe_expand_message(message: &mut IfMessagePart, basepath: &Path) -> anyhow::Result<()> { +async fn maybe_expand_message<F, R>(message: &mut IfMessagePart, opener: &F) -> anyhow::Result<()> +where + F: Fn(&str) -> anyhow::Result<BufReader<R>> + Clone + Send + 'static, + R: Read, +{ match message { IfMessagePart::Message(_) => Ok(()), IfMessagePart::Part { file, ref mut messages, } => { - let file_path = Path::new(file.as_str()); - let part_path = if let Some(parent) = basepath.parent() { - parent.join(file_path) - } else { - file_path.to_path_buf() - }; - let grit_part = parse_grit_part(part_path).await?; + let file = file.to_string(); + let opener = opener.clone(); + let grit_part = parse_grit_part_with_opener(move || opener(file.as_str())).await?; *messages = if_message_to_if_message_part(grit_part.messages); Ok(()) } @@ -1142,23 +1156,60 @@ async fn maybe_expand_message(message: &mut IfMessagePart, basepath: &Path) -> a expr: _, ref mut message, } => { - Box::pin(expand_messages(message, basepath)).await?; + Box::pin(expand_messages(message, opener)).await?; Ok(()) } } } -async fn expand_messages(messages: &mut Vec<IfMessagePart>, basepath: &Path) -> anyhow::Result<()> { +async fn expand_messages<F, R>(messages: &mut Vec<IfMessagePart>, opener: &F) -> anyhow::Result<()> +where + F: Fn(&str) -> anyhow::Result<BufReader<R>> + Clone + Send + 'static, + R: Read, +{ for message in messages { - maybe_expand_message(message, basepath).await?; + maybe_expand_message(message, opener).await?; } Ok(()) } pub async fn parse_grit_with_parts(path: impl AsRef<Path>) -> anyhow::Result<Grit> { let path = path.as_ref(); - let mut grit = parse_grit(path).await?; - expand_messages(&mut grit.release.messages.messages, path).await?; + if let Some(basepath) = path.parent() { + let basepath = basepath.to_path_buf(); + parse_grit_with_parts_and_resolver(path, move |x| basepath.join(x)).await + } else { + parse_grit_with_parts_and_resolver(path, |x| PathBuf::from(x)).await + } +} + +pub async fn parse_grit_with_parts_and_resolver<F>( + path: impl AsRef<Path>, + path_resolver: F, +) -> anyhow::Result<Grit> +where + F: Fn(&str) -> PathBuf + Send + Clone + 'static, +{ + let path = path.as_ref().to_path_buf(); + let grit_opener = || Ok(BufReader::new(fs::File::open(path)?)); + let part_opener = move |x: &str| { + let part_path = path_resolver(x); + Ok(BufReader::new(fs::File::open(part_path)?)) + }; + parse_grit_with_parts_and_opener(grit_opener, part_opener).await +} + +pub async fn parse_grit_with_parts_and_opener<F, G, R>( + grit_opener: F, + part_opener: G, +) -> anyhow::Result<Grit> +where + F: FnOnce() -> anyhow::Result<BufReader<R>> + Send + 'static, + G: Fn(&str) -> anyhow::Result<BufReader<R>> + Clone + Send + 'static, + R: Read, +{ + let mut grit = parse_grit_with_opener(grit_opener).await?; + expand_messages(&mut grit.release.messages.messages, &part_opener).await?; Ok(grit) } @@ -1513,9 +1564,16 @@ fn parse_xliff_element<R: Read>( pub async fn parse_xlf(path: impl AsRef<Path>) -> anyhow::Result<TranslationFile> { let path = path.as_ref().to_path_buf(); + parse_xlf_with_opener(|| Ok(BufReader::new(fs::File::open(path)?))).await +} + +pub async fn parse_xlf_with_opener<F, R>(opener: F) -> anyhow::Result<TranslationFile> +where + F: FnOnce() -> anyhow::Result<BufReader<R>> + Send + 'static, + R: Read, +{ spawn_blocking(move || { - let file = fs::File::open(path)?; - let reader = BufReader::new(file); + let reader = opener()?; let mut ereader = ParserConfig::new() .ignore_comments(true) .whitespace_to_characters(true) |
