use std::{fmt::Display, str::FromStr};
use quick_xml::{
Writer,
events::{BytesDecl, BytesStart, Event},
};
use crate::utils::{parse_attr_raw, try_get_attr_raw};
use crate::{Error, Result};
#[derive(Debug, Clone)]
pub struct OmapVersion {
xmlns: String,
version: u8,
}
impl<'writer> OmapVersion {
pub(crate) fn parse(element: &BytesStart<'_>) -> Result<Self> {
let xmlns = try_get_attr_raw(element, "xmlns");
let version = try_get_attr_raw(element, "version");
if let Some(xmlns) = xmlns
&& let Some(version) = version
{
Ok(OmapVersion { xmlns, version })
} else {
Err(Error::InvalidFormat(
"Could not read Omap version".to_string(),
))
}
}
pub(crate) fn write<W: std::io::Write>(self, writer: &'writer mut Writer<W>) -> Result<()> {
writer.write_event(Event::Start(
BytesStart::new("map").with_attributes(
[
("xmlns", self.xmlns.as_str()),
("version", self.version.to_string().as_str()),
]
.into_iter(),
),
))?;
Ok(())
}
}
impl Default for OmapVersion {
fn default() -> Self {
Self {
xmlns: "http://openorienteering.org/apps/mapper/xml/v2".into(),
version: 9,
}
}
}
#[derive(Debug, Clone)]
pub struct XmlVersion {
version: String,
encoding: Encoding,
}
impl Default for XmlVersion {
fn default() -> Self {
Self {
version: "1.0".to_string(),
encoding: Encoding::Utf8,
}
}
}
impl XmlVersion {
pub(crate) fn parse(decl: BytesDecl<'_>) -> Result<Self> {
let version = String::from_utf8(decl.version()?.into_owned())?;
let encoding = parse_attr_raw(decl.encoding().ok_or(Error::UnsupportedEncoding(
"No Encoding tag found".to_owned(),
))??)
.ok_or(Error::UnsupportedEncoding(
"No Encoding tag found".to_owned(),
))?;
Ok(XmlVersion { version, encoding })
}
pub(crate) fn write<W: std::io::Write>(self, writer: &mut Writer<W>) -> Result<()> {
writer.write_event(Event::Decl(BytesDecl::new(
self.version.as_str(),
Some(self.encoding.as_ref()),
None,
)))?;
Ok(())
}
pub fn version(&self) -> &str {
&self.version
}
pub fn encoding(&self) -> Encoding {
self.encoding
}
}
#[derive(Debug, Clone, Copy, Default)]
pub enum Encoding {
#[default]
Utf8,
}
impl AsRef<str> for Encoding {
fn as_ref(&self) -> &str {
match self {
Encoding::Utf8 => "UTF-8",
}
}
}
impl Display for Encoding {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Encoding::Utf8 => f.write_str("UTF-8"),
}
}
}
impl FromStr for Encoding {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"UTF-8" | "utf-8" | "Utf-8" => Ok(Encoding::Utf8),
_ => Err(Error::UnsupportedEncoding(s.to_string())),
}
}
}