use scroll::{Pread, LE};
use super::snow2_decryptor::Snow2Decryptor;
use crate::reader::Error;
pub(crate) struct Snow2Reader<'a> {
data: &'a [u8],
pub offset: usize,
decryptor: Snow2Decryptor,
pub buffer: [u8; 4],
pub buffer_len: usize,
}
impl<'a> Snow2Reader<'a> {
pub fn new(data: &'a [u8], snow_key: [u8; 16]) -> Self {
Self {
data,
offset: 0,
decryptor: Snow2Decryptor::new(snow_key),
buffer: [0_u8; 4],
buffer_len: 0,
}
}
#[allow(dead_code)]
pub fn read_u32(&mut self) -> Result<u32, Error> {
let decrypted = self
.decryptor
.decrypt_block(&self.data.pread_with::<u32>(self.offset, LE)?);
self.offset += 4;
if self.buffer_len > 0 {
let decrypted_bytes = decrypted.to_le_bytes();
let mut buffer = [0_u8; 4];
buffer[..self.buffer_len].copy_from_slice(&self.buffer[..self.buffer_len]);
buffer[self.buffer_len..].copy_from_slice(&decrypted_bytes[..4 - self.buffer_len]);
let result = buffer.pread_with::<u32>(0, LE)?;
self.buffer[..(4 - self.buffer_len)]
.copy_from_slice(&decrypted_bytes[self.buffer_len..]);
Ok(result)
} else {
Ok(decrypted)
}
}
pub fn read_i32(&mut self) -> Result<i32, Error> {
let decrypted = self
.decryptor
.decrypt_block(&self.data.pread_with::<u32>(self.offset, LE)?);
self.offset += 4;
let decrypted_bytes = decrypted.to_le_bytes();
if self.buffer_len > 0 {
let mut buffer = [0_u8; 4];
buffer[..self.buffer_len].copy_from_slice(&self.buffer[..self.buffer_len]);
buffer[self.buffer_len..].copy_from_slice(&decrypted_bytes[..4 - self.buffer_len]);
let result = buffer.pread_with::<i32>(0, LE)?;
self.buffer[..(4 - self.buffer_len)]
.copy_from_slice(&decrypted_bytes[self.buffer_len..]);
Ok(result)
} else {
Ok(i32::from_le_bytes(decrypted_bytes))
}
}
#[inline]
pub fn read_utf16_string(&mut self, len: usize) -> Result<String, Error> {
let string_vec = self.read_bytes(len)?;
let utf16_vec = string_vec
.chunks_exact(2)
.map(|u| u16::from_le_bytes([u[0], u[1]]))
.collect::<Vec<_>>();
String::from_utf16(&utf16_vec).map_err(Error::from)
}
#[inline]
pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, Error> {
let mut vec = vec![0_u8; len];
self.write_bytes_to(&mut vec, len)?;
Ok(vec)
}
pub fn write_bytes_to(&mut self, dest_buffer: &mut [u8], len: usize) -> Result<(), Error> {
let mut remaining_len = len as i32;
if self.buffer_len > 0 {
if len < self.buffer_len {
dest_buffer[0..len].copy_from_slice(&self.buffer[0..len]);
self.buffer_len -= len;
let mut temp_buffer = [0_u8; 4];
temp_buffer.copy_from_slice(&self.buffer[len..]);
self.buffer.copy_from_slice(&temp_buffer);
return Ok(());
}
dest_buffer[0..self.buffer_len].copy_from_slice(&self.buffer[0..self.buffer_len]);
remaining_len -= self.buffer_len as i32;
self.buffer_len = 0;
}
while remaining_len > 0 {
let decrypted = self
.decryptor
.decrypt_block(&self.data.pread_with::<u32>(self.offset, LE)?);
let bytes = decrypted.to_le_bytes();
let start = len - remaining_len as usize;
let dest_range = start..std::cmp::min(start + 4, len);
let data_len = dest_range.len();
dest_buffer[dest_range].copy_from_slice(&bytes[..data_len]);
self.offset += 4;
remaining_len -= 4;
if remaining_len < 0 {
let remaining_bytes = &bytes[data_len..];
self.buffer_len = remaining_bytes.len();
self.buffer[..self.buffer_len].copy_from_slice(remaining_bytes);
}
}
Ok(())
}
}