use std::io::Read;
use rkyv::rancor::Error as RkyvError;
use crate::codec::Decoder;
use crate::error::{RoxError, RoxResult};
use crate::model::{RoxChart, ROX_MAGIC};
use super::{RoxCodec, MAX_FILE_SIZE};
#[cfg(not(target_arch = "wasm32"))]
fn decompress(data: &[u8]) -> RoxResult<Vec<u8>> {
let mut decoder = zstd::stream::Decoder::new(data)?;
let mut decompressed = Vec::new();
decoder.read_to_end(&mut decompressed)?;
Ok(decompressed)
}
#[cfg(target_arch = "wasm32")]
fn decompress(data: &[u8]) -> RoxResult<Vec<u8>> {
Ok(data.to_vec())
}
fn delta_decode_notes(chart: &mut RoxChart) {
let mut accumulated_time: i64 = 0;
for note in &mut chart.notes {
accumulated_time += note.time_us; note.time_us = accumulated_time;
}
}
impl Decoder for RoxCodec {
fn decode(data: &[u8]) -> RoxResult<RoxChart> {
if data.len() < 4 || data[..4] != ROX_MAGIC {
return Err(RoxError::InvalidFormat(
"Invalid ROX file: missing magic bytes".into(),
));
}
if data.len() > MAX_FILE_SIZE {
return Err(RoxError::InvalidFormat(format!(
"File too large: {} bytes (max {}MB)",
data.len(),
MAX_FILE_SIZE / 1024 / 1024
)));
}
let decompressed = decompress(&data[4..])?;
let mut chart: RoxChart = rkyv::from_bytes::<RoxChart, RkyvError>(&decompressed)
.map_err(|e| RoxError::Deserialize(e.to_string()))?;
delta_decode_notes(&mut chart);
Ok(chart)
}
}