use crate::helpers::{strip_bom, fold_lis};
use std::path::Path;
use xml::reader::{
EventReader,
XmlEvent,
};
#[allow(non_snake_case)]
#[derive(Debug, Clone, Default)]
pub struct ModsConfig {
pub version: Option<String>,
pub activeMods: Vec<String>,
pub knownExpansions: Vec<String>,
}
impl TryFrom<&[u8]> for ModsConfig {
type Error = xml::reader::Error;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
enum Section {
Version,
ActiveMods,
KnownExpansions,
}
let reader = EventReader::new(strip_bom(bytes));
let mut mods_config = Self::default();
let mut section: Option<Section> = None;
for event in reader {
match event? {
XmlEvent::StartElement { name, .. } => {
if name.local_name == "version" {
section = Some(Section::Version);
} else if name.local_name == "activeMods" {
section = Some(Section::ActiveMods);
} else if name.local_name == "knownExpansions" {
section = Some(Section::KnownExpansions);
}
}
XmlEvent::EndElement { name } => {
if name.local_name == "version" || name.local_name == "activeMods" || name.local_name == "knownExpansions" {
section = None;
}
}
XmlEvent::Characters(text) => {
match section.as_ref().expect("Unexpected Characters when parsing `ModsConfig`") {
Section::Version => mods_config.version = Some(text),
Section::ActiveMods => mods_config.activeMods.push(text),
Section::KnownExpansions => mods_config.knownExpansions.push(text),
}
}
_ => {}
}
}
Ok(mods_config)
}
}
impl TryFrom<&Path> for ModsConfig {
type Error = super::ParseXMLError;
fn try_from(path: &Path) -> Result<Self, Self::Error> {
let bytes = std::fs::read(path)?;
Self::try_from(bytes.as_slice())
.map_err(std::convert::Into::into)
}
}
impl From<ModsConfig> for String {
fn from(mods_config: ModsConfig) -> Self {
let mut out = String::from("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ModsConfigData>\n");
if let Some(version) = &mods_config.version {
out.push_str(&format!(" <version>{version}</version>\n"));
}
if !mods_config.activeMods.is_empty() {
out.push_str(" <activeMods>\n");
out.push_str(&fold_lis(mods_config.activeMods, 2));
out.push_str(" </activeMods>\n");
}
if !mods_config.knownExpansions.is_empty() {
out.push_str(" <knownExpansions>\n");
out.push_str(&fold_lis(mods_config.knownExpansions, 2));
out.push_str(" </knownExpansions>\n");
}
out.push_str("</ModsConfigData>");
out
}
}