use std::io::Write;
use rkyv::rancor::Error as RkyvError;
use crate::codec::Encoder;
use crate::error::{RoxError, RoxResult};
use crate::model::{RoxChart, ROX_MAGIC};
use super::RoxCodec;
#[cfg(not(target_arch = "wasm32"))]
const COMPRESSION_LEVEL: i32 = 3;
#[cfg(not(target_arch = "wasm32"))]
fn compress(data: &[u8]) -> RoxResult<Vec<u8>> {
let mut encoder = zstd::stream::Encoder::new(Vec::new(), COMPRESSION_LEVEL)?;
encoder.write_all(data)?;
Ok(encoder.finish()?)
}
#[cfg(target_arch = "wasm32")]
fn compress(data: &[u8]) -> RoxResult<Vec<u8>> {
Ok(data.to_vec())
}
fn delta_encode_notes(chart: &RoxChart) -> RoxChart {
let mut result = chart.clone();
let mut last_time: i64 = 0;
for note in &mut result.notes {
let original_time = note.time_us;
note.time_us = original_time - last_time; last_time = original_time;
}
result
}
impl Encoder for RoxCodec {
fn encode(chart: &RoxChart) -> RoxResult<Vec<u8>> {
chart.validate()?;
let delta_chart = delta_encode_notes(chart);
let encoded = rkyv::to_bytes::<RkyvError>(&delta_chart)
.map_err(|e| RoxError::Serialize(e.to_string()))?;
let compressed = compress(&encoded)?;
let mut data = ROX_MAGIC.to_vec();
data.extend(compressed);
Ok(data)
}
}