Files
PurrfectSnap/native/rust/src/modules/util/composer_utils.rs
2024-07-28 20:13:27 +02:00

142 lines
3.6 KiB
Rust

use std::{io::Error, string::FromUtf8Error};
#[derive(Debug, Clone)]
pub struct ModuleTag {
tag_type: u8,
buffer: Vec<u8>,
}
impl ModuleTag {
pub fn new(module_type: u8, buffer: Vec<u8>) -> ModuleTag {
ModuleTag {
tag_type: module_type,
buffer,
}
}
pub fn to_string(&self) -> Result<String, FromUtf8Error> {
Ok(String::from_utf8(self.buffer.clone())?)
}
pub fn get_tag_type(&self) -> u8 {
self.tag_type
}
pub fn get_size(&self) -> usize {
self.buffer.len()
}
pub fn get_buffer(&self) -> &Vec<u8> {
&self.buffer
}
pub fn set_buffer(&mut self, buffer: Vec<u8>) {
self.buffer = buffer;
}
}
#[derive(Debug, Clone)]
pub struct ComposerModule {
tags: Vec<(ModuleTag, ModuleTag)>, // file name => file content
}
impl ComposerModule {
pub fn parse(buffer: Vec<u8>) -> Result<ComposerModule, Error> {
let mut offset = 0;
let magic = u32::from_be_bytes([buffer[offset], buffer[offset + 1], buffer[offset + 2], buffer[offset + 3]]);
offset += 4;
if magic != 0x33c60001 {
return Err(Error::new(std::io::ErrorKind::InvalidData, "Invalid magic"));
}
// skip content length
offset += 4;
let mut tags = Vec::new();
loop {
if offset >= buffer.len() {
break;
}
fn read_u24(buffer: &Vec<u8>, offset: &mut usize) -> Result<u32, Error> {
let b1 = buffer[*offset] as u32;
let b2 = buffer[*offset + 1] as u32;
let b3 = buffer[*offset + 2] as u32;
*offset += 3;
Ok(b1 | (b2 << 8) | (b3 << 16))
}
let tag_size = read_u24(&buffer, &mut offset)?;
let tag_type = buffer[offset];
offset += 1;
let tag_buffer = buffer[offset..offset + tag_size as usize].to_vec();
offset += tag_size as usize;
let padding = 4 - (tag_size % 4);
if padding != 4 {
offset += padding as usize;
}
tags.push(ModuleTag::new(tag_type, tag_buffer));
}
let tags = tags.chunks(2).map(|chunk| {
(chunk[0].clone(), chunk[1].clone())
}).collect();
Ok(ComposerModule {
tags,
})
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut tag_buffer = Vec::new();
fn write_u24(buffer: &mut Vec<u8>, value: u32) {
buffer.push((value & 0xff) as u8);
buffer.push(((value >> 8) & 0xff) as u8);
buffer.push(((value >> 16) & 0xff) as u8);
}
fn write_tag(buffer: &mut Vec<u8>, tag: ModuleTag) {
write_u24(buffer, tag.get_size() as u32);
buffer.push(tag.get_tag_type());
buffer.extend(tag.get_buffer());
let padding = 4 - (tag.get_size() % 4);
if padding != 4 {
for _ in 0..padding {
buffer.push(0);
}
}
}
for (tag1, tag2) in &self.tags {
write_tag(&mut tag_buffer, tag1.clone());
write_tag(&mut tag_buffer, tag2.clone());
}
let mut buffer = Vec::new();
buffer.extend_from_slice(&[0x33, 0xc6, 0, 1]);
buffer.extend_from_slice(&(tag_buffer.len() as u32).to_le_bytes());
buffer.extend(tag_buffer);
buffer
}
pub fn get_tags(&self) -> Vec<(ModuleTag, ModuleTag)> {
self.tags.clone()
}
pub fn set_tags(&mut self, tags: Vec<(ModuleTag, ModuleTag)>) {
self.tags = tags;
}
}