1use crate::{Element, Entry};
2use std::{io, mem};
3use thiserror::Error;
4
5#[derive(Error, Debug)]
7pub enum Error {
8 #[error("Unknown error")]
14 Unknown,
15
16 #[error("I/O error while writing TPK data: {source}")]
18 Io {
19 #[from]
20 source: io::Error,
21 },
22}
23
24pub type Result<T> = std::result::Result<T, Error>;
26
27pub struct Writer<T> {
31 write: T,
32}
33
34impl<T> Writer<T>
35where
36 T: io::Write,
37{
38 pub fn new(write: T) -> Writer<T> {
40 Writer { write }
41 }
42
43 pub fn write_element(&mut self, element: &Element) -> Result<()> {
51 self.write.write_all(&[element.get_type_byte()])?;
52
53 match *element {
54 Element::Marker(ref val) => {
55 let size = val.len();
56 if size > 63 {
57 let remaining_size = size >> 6;
58 let dynsize = dyn_size(remaining_size);
59 self.write.write_all(dynsize.as_slice())?;
60 }
61 self.write.write_all(val.as_bytes())?;
62 }
63 Element::Integer8(val) => {
64 self.write.write_all(&[val as u8])?;
65 }
66 Element::Integer16(val) => {
67 self.write.write_all(&val.to_le_bytes())?;
68 }
69 Element::Integer32(val) => {
70 self.write.write_all(&val.to_le_bytes())?;
71 }
72 Element::Integer64(val) => {
73 self.write.write_all(&val.to_le_bytes())?;
74 }
75 Element::UInteger8(val) => {
76 self.write.write_all(&[val])?;
77 }
78 Element::UInteger16(val) => {
79 self.write.write_all(&val.to_le_bytes())?;
80 }
81 Element::UInteger32(val) => {
82 self.write.write_all(&val.to_le_bytes())?;
83 }
84 Element::UInteger64(val) => {
85 self.write.write_all(&val.to_le_bytes())?;
86 }
87 Element::Float32(val) => {
88 self.write.write_all(&val.to_le_bytes())?;
89 }
90 Element::Float64(val) => {
91 self.write.write_all(&val.to_le_bytes())?;
92 }
93 Element::String(ref val) => {
94 let bytes = val.as_bytes();
95 self.write.write_all(&static_size(bytes.len()))?;
96 self.write.write_all(bytes)?;
97 }
98 Element::Blob(ref val) => {
99 self.write.write_all(&static_size(val.len()))?;
100 self.write.write_all(val.as_slice())?;
101 }
102 _ => (),
103 };
104 Ok(())
105 }
106
107 pub fn write_entry(&mut self, entry: &Entry) -> Result<()> {
116 let marker = Element::Marker(entry.name.clone());
117 self.write_element(&marker)?;
118 for element in &entry.elements {
119 self.write_element(element)?;
120 }
121 Ok(())
122 }
123}
124
125fn static_size(size: usize) -> Vec<u8> {
126 match size {
127 0..=255 => Vec::from([size as u8]),
128 256..=65535 => Vec::from((size as u16).to_le_bytes()),
129 65536..=4294967295 => Vec::from((size as u32).to_le_bytes()),
130 _ => Vec::from((size as u64).to_le_bytes()),
131 }
132}
133
134fn dyn_size(size: usize) -> Vec<u8> {
135 if size == 0 {
136 return Vec::from([0u8]);
137 }
138
139 let fls = if size == 0 {
140 0u32
141 } else {
142 mem::size_of::<usize>() as u32 * 8u32 - size.leading_zeros()
143 };
144
145 let mut ret = Vec::with_capacity((fls / 7) as usize);
146
147 let mut size = size;
148 while size > 0 {
149 ret.push((size as u8 & 0x7F) | if size > 0x7F { 0b10000000u8 } else { 0u8 });
150 size >>= 7;
151 }
152 ret
153}