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 {}