use std::{
io,
path::{Path, PathBuf},
};
#[derive(Debug, Clone)]
pub struct QResourceFile {
alias: Option<String>,
path: PathBuf,
}
impl<T: AsRef<Path>> From<T> for QResourceFile {
fn from(value: T) -> Self {
Self::new(value)
}
}
impl QResourceFile {
pub fn new(path: impl AsRef<Path>) -> Self {
Self {
alias: None,
path: path.as_ref().to_path_buf(),
}
}
pub fn alias(mut self, alias: impl Into<String>) -> Self {
self.alias = Some(alias.into());
self
}
pub fn get_path(&self) -> &Path {
&self.path
}
fn write(self, writer: &mut impl io::Write) -> io::Result<()> {
let alias = self
.alias
.unwrap_or_else(|| self.path.to_string_lossy().to_string());
let alias = alias.escape_default();
#[cfg(test)]
let path = &self.path;
#[cfg(not(test))]
let path = std::fs::canonicalize(self.path)?;
writeln!(
writer,
" <file alias=\"{alias}\">{path}</file>",
path = path.display()
)
}
}
#[derive(Debug, Clone)]
pub struct QResource {
language: Option<String>,
prefix: Option<String>,
files: Vec<QResourceFile>,
}
impl Default for QResource {
fn default() -> Self {
Self::new()
}
}
impl<T: Into<QResourceFile>> From<T> for QResource {
fn from(value: T) -> Self {
Self::new().file(value)
}
}
impl QResource {
pub fn new() -> Self {
Self {
language: None,
prefix: None,
files: vec![],
}
}
pub fn file<T: Into<QResourceFile>>(mut self, file: T) -> Self {
self.files.push(file.into());
self
}
pub fn files<T: Into<QResourceFile>>(mut self, files: impl IntoIterator<Item = T>) -> Self {
for file in files.into_iter() {
self.files.push(file.into());
}
self
}
pub fn get_files(&self) -> impl Iterator<Item = &QResourceFile> {
self.files.iter()
}
pub fn language(mut self, language: impl Into<String>) -> Self {
self.language = Some(language.into());
self
}
pub fn prefix(mut self, prefix: impl Into<String>) -> Self {
self.prefix = Some(prefix.into());
self
}
pub fn get_prefix(&self) -> Option<&str> {
self.prefix.as_deref()
}
fn write(self, writer: &mut impl io::Write) -> io::Result<()> {
let language = self
.language
.map(|language| format!(" language=\"{}\"", language.escape_default()))
.unwrap_or_default();
let prefix = self
.prefix
.map(|prefix| format!(" prefix=\"{}\"", prefix.escape_default()))
.unwrap_or_default();
writeln!(writer, " <qresource{language}{prefix}>")?;
for file in self.files.into_iter() {
file.write(writer)?;
}
writeln!(writer, " </qresource>")
}
}
#[derive(Debug, Clone)]
pub struct QResources {
resources: Vec<QResource>,
}
impl Default for QResources {
fn default() -> Self {
Self::new()
}
}
impl<T: IntoIterator<Item = impl Into<QResourceFile>>> From<T> for QResources {
fn from(value: T) -> Self {
Self::new().resource(QResource::new().files(value))
}
}
impl QResources {
pub fn new() -> Self {
Self { resources: vec![] }
}
pub fn resource<T: Into<QResource>>(mut self, resource: T) -> Self {
self.resources.push(resource.into());
self
}
pub fn resources<T: Into<QResource>>(mut self, resources: impl IntoIterator<Item = T>) -> Self {
for resource in resources.into_iter() {
self.resources.push(resource.into());
}
self
}
pub fn get_resources_mut(&mut self) -> impl Iterator<Item = &mut QResource> {
self.resources.iter_mut()
}
pub fn get_resources(&self) -> impl Iterator<Item = &QResource> {
self.resources.iter()
}
pub fn write(self, writer: &mut impl io::Write) -> io::Result<()> {
writeln!(writer, "<RCC>")?;
for resource in self.resources.into_iter() {
resource.write(writer)?;
}
writeln!(writer, "</RCC>")
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn resource_file() {
let mut result = Vec::new();
QResourceFile::new("path")
.alias("alias")
.write(&mut result)
.unwrap();
assert_eq!(
String::from_utf8(result).unwrap(),
" <file alias=\"alias\">path</file>\n"
);
}
#[test]
fn resource() {
let mut result = Vec::new();
QResource::new()
.language("language")
.prefix("prefix")
.write(&mut result)
.unwrap();
assert_eq!(
String::from_utf8(result).unwrap(),
" <qresource language=\"language\" prefix=\"prefix\">\n </qresource>\n"
);
}
#[test]
fn resources() {
let mut result = Vec::new();
QResources::new()
.resources(["a", "b"])
.resource(
QResource::new()
.prefix("prefix")
.files(["c", "d"])
.file(QResourceFile::new("e").alias("alias")),
)
.write(&mut result)
.unwrap();
assert_eq!(
String::from_utf8(result).unwrap(),
"<RCC>
<qresource>
<file alias=\"a\">a</file>
</qresource>
<qresource>
<file alias=\"b\">b</file>
</qresource>
<qresource prefix=\"prefix\">
<file alias=\"c\">c</file>
<file alias=\"d\">d</file>
<file alias=\"alias\">e</file>
</qresource>
</RCC>
"
);
}
#[test]
fn resources_from_files() {
let mut result = Vec::new();
QResources::from(["a", "b"]).write(&mut result).unwrap();
assert_eq!(
String::from_utf8(result).unwrap(),
format!(
"<RCC>
<qresource>
<file alias=\"a\">a</file>
<file alias=\"b\">b</file>
</qresource>
</RCC>
",
)
);
}
}