criware_utf_core/
packet.rs1use std::{
2 alloc::{self, Layout},
3 io::{Cursor, Read, Write},
4 ops::{Deref, DerefMut},
5};
6
7use crate::{Error, IOErrorHelper, Result, Table};
8
9mod cri_encryption;
10
11fn aligned_vec(initial_size: usize, size: usize) -> Vec<u8> {
12 let minimum_size = size.div_ceil(64) << 6;
13 let layout = Layout::from_size_align(minimum_size, 64).expect("Invalid layout");
14 unsafe {
15 let ptr = alloc::alloc(layout);
16 if ptr.is_null() {
17 alloc::handle_alloc_error(layout);
18 }
19 Vec::from_raw_parts(ptr, initial_size, minimum_size)
20 }
21}
22fn aligned_vec_empty() -> Vec<u8> {
23 aligned_vec(0, 256)
24}
25fn aligned_vec_full(size: usize) -> Vec<u8> {
26 aligned_vec(size, size)
27}
28
29pub struct Packet<T: Table> {
33 prefix: &'static [u8; 4],
34 encrypted: bool,
35 unknown_value: u32,
36 table: T,
37}
38
39impl<T: Table> Packet<T> {
40 pub fn new(prefix: &'static [u8; 4]) -> Self {
46 Self::from_table(T::new(), prefix)
47 }
48
49 pub fn from_table(table: T, prefix: &'static [u8; 4]) -> Self {
53 Packet {
54 prefix,
55 encrypted: false,
56 unknown_value: 0,
57 table,
58 }
59 }
60
61 pub fn read_packet(reader: &mut dyn Read, prefix: &'static [u8; 4]) -> Result<Self> {
66 let mut header = [0u8; 16];
67 reader.read_exact(&mut header).io("UTF packet header")?;
68 if prefix != &header[0..4] {
69 return Err(Error::WrongTableSchema);
70 }
71 let unknown_value = u32::from_le_bytes(header[4..8].try_into().unwrap());
72 let table_size = u64::from_le_bytes(header[8..16].try_into().unwrap());
73 if table_size < 32 {
74 return Err(Error::MalformedHeader);
75 }
76 let mut table_data = aligned_vec_full(table_size as usize);
77 let mut decrypted_table_data = aligned_vec_full(table_size as usize);
78 reader
79 .read_exact(table_data.as_mut_slice())
80 .io("UTF table")?;
81 if &table_data[0..4] == b"@UTF" {
82 return Ok(Packet {
83 prefix,
84 encrypted: false,
85 unknown_value,
86 table: T::read(&mut Cursor::new(table_data))?,
87 });
88 }
89 if !cri_encryption::can_decrypt(table_data.as_slice()) {
90 return Err(Error::DecryptionError);
91 }
92 cri_encryption::decrypt(table_data.as_slice(), decrypted_table_data.as_mut_slice());
93 if &decrypted_table_data[0..4] == b"@UTF" {
94 return Ok(Packet {
95 prefix,
96 encrypted: true,
97 unknown_value,
98 table: T::read(&mut Cursor::new(decrypted_table_data))?,
99 });
100 }
101 return Err(Error::DecryptionError);
102 }
103
104 pub fn write_packet(&self, writer: &mut dyn Write) -> Result<()> {
108 let mut table_buffer = Cursor::new(aligned_vec_empty());
109 self.table.write(&mut table_buffer)?;
110 let table_buffer = {
111 let mut buffer = table_buffer.into_inner();
112 if buffer.capacity() < buffer.len().div_ceil(64) << 6 {
113 buffer.reserve_exact(64 - (buffer.len() & 63));
114 }
115 if self.encrypted {
116 let mut new_buffer = aligned_vec_full(buffer.len());
117 cri_encryption::encrypt(buffer.as_slice(), new_buffer.as_mut_slice());
118 new_buffer
119 } else {
120 buffer
121 }
122 };
123 writer.write_all(self.prefix).io("UTF packet header")?;
124 writer
125 .write_all(&u32::to_le_bytes(self.unknown_value))
126 .io("UTF packet header")?;
127 writer
128 .write_all(&u64::to_le_bytes(table_buffer.len() as u64))
129 .io("UTF packet header")?;
130 writer
131 .write_all(table_buffer.as_slice())
132 .io("UTF packet table")?;
133 Ok(())
134 }
135
136 pub fn is_encrypted(&self) -> bool {
140 self.encrypted
141 }
142
143 pub fn disable_encryption(&mut self) {
147 self.encrypted = false;
148 }
149
150 pub fn enable_encryption(&mut self) {
154 self.encrypted = true;
155 }
156}
157
158impl<T: Table> Deref for Packet<T> {
159 type Target = T;
160
161 fn deref(&self) -> &Self::Target {
162 &self.table
163 }
164}
165
166impl<T: Table> DerefMut for Packet<T> {
167 fn deref_mut(&mut self) -> &mut Self::Target {
168 &mut self.table
169 }
170}