1#![allow(unused)]
2
3mod archive;
4mod error;
5mod padding;
6
7pub(crate) mod prelude {
8  pub(crate) use crate::archive::Key;
9  pub(crate) use crate::error::Error;
10  pub(crate) use crate::padding::Padding;
11  pub(crate) use crate::Result;
12  pub(crate) use crate::{ReadEncryptedBytes, ReadTracing, WriteEncryptedBytes, WriteTracing};
13  pub(crate) use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
14  pub(crate) use std::io::{Cursor, Read, Seek, SeekFrom, Write};
15  #[cfg(test)]
16  pub(crate) use test_strategy::Arbitrary;
17}
18
19use prelude::*;
20
21pub use archive::Archive;
22pub use archive::Header;
23pub use archive::Key;
24pub use error::Error;
25
26pub type Result<T> = std::result::Result<T, Error>;
27
28pub(crate) trait ReadEncryptedBytes: ReadBytesExt {
29  fn read_encrypted_u8(&mut self, key: Key) -> std::io::Result<u8> {
30    self.read_u8().map(|value| value ^ key)
31  }
32
33  fn read_encrypted_bool(&mut self, key: Key) -> std::io::Result<bool> {
34    self.read_encrypted_u8(key).map(|value| value != 0)
35  }
36
37  fn read_encrypted_u32<T: ByteOrder>(&mut self, key: Key) -> std::io::Result<u32> {
38    self.read_u32::<T>().map(|value| value ^ key)
39  }
40
41  fn read_encrypted_varint(&mut self, key: Key) -> Result<usize> {
42    match self.read_encrypted_u8(key) {
43      Err(error) => Err(error.into()),
44      Ok(value) if value & 0x80 != 0 => Err(Error::VarIntSupportNotImplemented),
45      Ok(value) => Ok((value & 0x7F).into()),
46    }
47  }
48
49  fn read_encrypted_bytes(&mut self, key: Key) -> Result<Vec<u8>> {
50    let mut bytes = Vec::with_capacity(self.read_encrypted_varint(key)?);
51    for _ in 0..bytes.capacity() {
52      let byte = self.read_encrypted_u8(key)?;
53      bytes.push(byte);
54    }
55
56    Ok(bytes)
57  }
58
59  fn read_encrypted_string(&mut self, key: Key) -> Result<String> {
60    let bytes = self.read_encrypted_bytes(key)?;
61    let string = String::from_utf8(bytes)?;
62    Ok(string)
63  }
64}
65
66impl<T> ReadEncryptedBytes for T where T: ReadBytesExt {}
67
68pub(crate) trait WriteEncryptedBytes: WriteBytesExt {
69  fn write_encrypted_u8(&mut self, value: u8, key: Key) -> std::io::Result<()> {
70    self.write_u8(value ^ key)
71  }
72
73  fn write_encrypted_bool(&mut self, value: bool, key: Key) -> std::io::Result<()> {
74    self.write_encrypted_u8(value.into(), key)
75  }
76
77  fn write_encrypted_u32<T: ByteOrder>(&mut self, value: u32, key: Key) -> std::io::Result<()> {
78    self.write_u32::<T>(value ^ key)
79  }
80
81  fn write_encrypted_varint(&mut self, value: usize, key: Key) -> Result<()> {
82    match u8::try_from(value) {
83      Err(error) => Err(error.into()),
84      Ok(value) if value & 0x80 != 0 => Err(Error::VarIntSupportNotImplemented),
85      Ok(value) => self.write_encrypted_u8(value, key).map_err(Into::into),
86    }
87  }
88
89  fn write_encrypted_bytes(&mut self, bytes: &[u8], key: Key) -> Result<()> {
90    self.write_encrypted_varint(bytes.len(), key)?;
91
92    for &byte in bytes {
93      self.write_encrypted_u8(byte, key)?;
94    }
95
96    Ok(())
97  }
98
99  fn write_encrypted_string(&mut self, string: &str, key: Key) -> Result<()> {
100    self.write_encrypted_bytes(string.as_bytes(), key)
101  }
102}
103
104impl<T> WriteEncryptedBytes for T where T: WriteBytesExt {}
105
106pub(crate) trait ReadTracing: Read + Seek {
107  fn trace<F: FnMut(&mut Self) -> Result<T>, T>(&mut self, mut function: F) -> Result<T> {
108    #[cfg(not(feature = "logging"))]
109    return function(self);
110
111    #[cfg(feature = "logging")]
112    {
113      let initial_stream_position = self.stream_position()?;
114      log::trace!("read -> address={:#010X?}", initial_stream_position);
115
116      let value = function(self)?;
117
118      let final_stream_position = self.stream_position()?;
119      log::trace!("read size={}", final_stream_position - initial_stream_position);
120      log::trace!("read <- address={:#010X?}", final_stream_position);
121
122      Ok(value)
123    }
124  }
125}
126
127impl<T> ReadTracing for T where T: Read + Seek {}
128
129pub(crate) trait WriteTracing: Write + Seek {
130  fn trace<F: FnMut(&mut Self) -> Result<T>, T>(&mut self, mut function: F) -> Result<T> {
131    #[cfg(not(feature = "logging"))]
132    return function(self);
133
134    #[cfg(feature = "logging")]
135    {
136      let initial_stream_position = self.stream_position()?;
137      log::trace!("write -> address={:#010X?}", initial_stream_position);
138
139      let value = function(self)?;
140
141      let final_stream_position = self.stream_position()?;
142      log::trace!("write size={}", final_stream_position - initial_stream_position);
143      log::trace!("write <- address={:#010X?}", final_stream_position);
144
145      Ok(value)
146    }
147  }
148}
149
150impl<T> WriteTracing for T where T: Write + Seek {}