use crate::File;
use crate::lx::cipher;
use quick_xml;
use quick_xml::events::{BytesDecl, BytesEnd, BytesStart, BytesText, Event};
use std::io::{Cursor, Write};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum EncodeError {
#[error(transparent)]
Xml(#[from] quick_xml::Error),
}
pub fn encode_file(file: &File) -> Result<Vec<u8>, EncodeError> {
let mut writer = Writer::new(Cursor::new(Vec::new()));
writer.write(file)?;
let xml = writer.into_inner().into_inner();
Ok(xml)
}
#[derive(Clone)]
pub struct Writer<W: Write> {
xml_writer: quick_xml::Writer<cipher::Writer<W>>,
}
impl<W: Write> Writer<W> {
pub fn new(inner: W) -> Self {
let cipher_writer = cipher::Writer::new(inner);
let xml_writer = quick_xml::Writer::new(cipher_writer);
Self { xml_writer }
}
pub fn write(&mut self, file: &File) -> Result<(), EncodeError> {
let writer = &mut self.xml_writer;
writer.write_event(Event::Decl(BytesDecl::new("1.0", Some("UTF-8"), None)))?;
writer.write_event(Event::Text(BytesText::from_escaped("\n")))?;
let version = format!("{:06x?}", file.version);
writer.write_event(Event::Start(
BytesStart::new("FLARMNET")
.with_attributes(vec![("Version".as_bytes(), version.as_bytes())]),
))?;
writer.write_event(Event::Text(BytesText::from_escaped("\n")))?;
for record in &file.records {
writer
.write_event(Event::Start(BytesStart::new("FLARMDATA").with_attributes(
vec![("FlarmID".as_bytes(), record.flarm_id.as_bytes())],
)))?;
if !record.pilot_name.is_empty() {
writer.write_event(Event::Start(BytesStart::new("NAME")))?;
writer.write_event(Event::Text(BytesText::new(&record.pilot_name)))?;
writer.write_event(Event::End(BytesEnd::new("NAME")))?;
}
if !record.airfield.is_empty() {
writer.write_event(Event::Start(BytesStart::new("AIRFIELD")))?;
writer.write_event(Event::Text(BytesText::new(&record.airfield)))?;
writer.write_event(Event::End(BytesEnd::new("AIRFIELD")))?;
}
if !record.plane_type.is_empty() {
writer.write_event(Event::Start(BytesStart::new("TYPE")))?;
writer.write_event(Event::Text(BytesText::new(&record.plane_type)))?;
writer.write_event(Event::End(BytesEnd::new("TYPE")))?;
}
if !record.registration.is_empty() {
writer.write_event(Event::Start(BytesStart::new("REG")))?;
writer.write_event(Event::Text(BytesText::new(&record.registration)))?;
writer.write_event(Event::End(BytesEnd::new("REG")))?;
}
if !record.call_sign.is_empty() {
writer.write_event(Event::Start(BytesStart::new("COMPID")))?;
writer.write_event(Event::Text(BytesText::new(&record.call_sign)))?;
writer.write_event(Event::End(BytesEnd::new("COMPID")))?;
}
if !record.frequency.is_empty() {
writer.write_event(Event::Start(BytesStart::new("FREQUENCY")))?;
writer.write_event(Event::Text(BytesText::new(&record.frequency)))?;
writer.write_event(Event::End(BytesEnd::new("FREQUENCY")))?;
}
writer.write_event(Event::End(BytesEnd::new("FLARMDATA")))?;
writer.write_event(Event::Text(BytesText::from_escaped("\n")))?;
}
writer.write_event(Event::End(BytesEnd::new("FLARMNET")))?;
Ok(())
}
pub fn into_inner(self) -> W {
self.xml_writer.into_inner().into_inner()
}
}