1use crate::lx::cipher;
2use crate::File;
3use quick_xml;
4use quick_xml::events::{BytesDecl, BytesEnd, BytesStart, BytesText, Event};
5use std::io::{Cursor, Write};
6use thiserror::Error;
7
8#[derive(Error, Debug)]
9pub enum EncodeError {
10 #[error(transparent)]
11 Xml(#[from] quick_xml::Error),
12}
13
14pub fn encode_file(file: &File) -> Result<Vec<u8>, EncodeError> {
39 let mut writer = Writer::new(Cursor::new(Vec::new()));
40 writer.write(file)?;
41
42 let xml = writer.into_inner().into_inner();
43
44 Ok(xml)
45}
46
47#[derive(Clone)]
48pub struct Writer<W: Write> {
49 xml_writer: quick_xml::Writer<cipher::Writer<W>>,
50}
51
52impl<W: Write> Writer<W> {
53 pub fn new(inner: W) -> Self {
54 let cipher_writer = cipher::Writer::new(inner);
55 let xml_writer = quick_xml::Writer::new(cipher_writer);
56
57 Self { xml_writer }
58 }
59
60 pub fn write(&mut self, file: &File) -> Result<(), EncodeError> {
61 let writer = &mut self.xml_writer;
62
63 writer.write_event(Event::Decl(BytesDecl::new("1.0", Some("UTF-8"), None)))?;
64 writer.write_event(Event::Text(BytesText::from_escaped("\n")))?;
65
66 let version = format!("{:06x?}", file.version);
67 writer.write_event(Event::Start(
68 BytesStart::new("FLARMNET")
69 .with_attributes(vec![("Version".as_bytes(), version.as_bytes())]),
70 ))?;
71 writer.write_event(Event::Text(BytesText::from_escaped("\n")))?;
72
73 for record in &file.records {
74 writer
75 .write_event(Event::Start(BytesStart::new("FLARMDATA").with_attributes(
76 vec![("FlarmID".as_bytes(), record.flarm_id.as_bytes())],
77 )))?;
78
79 if !record.pilot_name.is_empty() {
80 writer.write_event(Event::Start(BytesStart::new("NAME")))?;
81 writer.write_event(Event::Text(BytesText::new(&record.pilot_name)))?;
82 writer.write_event(Event::End(BytesEnd::new("NAME")))?;
83 }
84
85 if !record.airfield.is_empty() {
86 writer.write_event(Event::Start(BytesStart::new("AIRFIELD")))?;
87 writer.write_event(Event::Text(BytesText::new(&record.airfield)))?;
88 writer.write_event(Event::End(BytesEnd::new("AIRFIELD")))?;
89 }
90
91 if !record.plane_type.is_empty() {
92 writer.write_event(Event::Start(BytesStart::new("TYPE")))?;
93 writer.write_event(Event::Text(BytesText::new(&record.plane_type)))?;
94 writer.write_event(Event::End(BytesEnd::new("TYPE")))?;
95 }
96
97 if !record.registration.is_empty() {
98 writer.write_event(Event::Start(BytesStart::new("REG")))?;
99 writer.write_event(Event::Text(BytesText::new(&record.registration)))?;
100 writer.write_event(Event::End(BytesEnd::new("REG")))?;
101 }
102
103 if !record.call_sign.is_empty() {
104 writer.write_event(Event::Start(BytesStart::new("COMPID")))?;
105 writer.write_event(Event::Text(BytesText::new(&record.call_sign)))?;
106 writer.write_event(Event::End(BytesEnd::new("COMPID")))?;
107 }
108
109 if !record.frequency.is_empty() {
110 writer.write_event(Event::Start(BytesStart::new("FREQUENCY")))?;
111 writer.write_event(Event::Text(BytesText::new(&record.frequency)))?;
112 writer.write_event(Event::End(BytesEnd::new("FREQUENCY")))?;
113 }
114
115 writer.write_event(Event::End(BytesEnd::new("FLARMDATA")))?;
116 writer.write_event(Event::Text(BytesText::from_escaped("\n")))?;
117 }
118 writer.write_event(Event::End(BytesEnd::new("FLARMNET")))?;
119
120 Ok(())
121 }
122
123 pub fn into_inner(self) -> W {
124 self.xml_writer.into_inner().into_inner()
125 }
126}