zstd encode

This commit is contained in:
2026-02-13 08:46:10 -08:00
parent 46b5568b4f
commit b1ed436fe0

View File

@@ -746,6 +746,7 @@ pub fn serialize<W:binrw::BinWriterExt>(block:&Block,writer:&mut W)->Result<(),B
use std::ops::Range;
const MAX_BLOCK_SIZE:usize=1<<18;
const FILE_VERSION:u32=1;
const COMPRESSION_LEVEL:i32=19;
const EVENT_TYPES:[EventType;8]=[
EventType::Input,
EventType::Output,
@@ -896,7 +897,40 @@ pub fn serialize<W:binrw::BinWriterExt>(block:&Block,writer:&mut W)->Result<(),B
num_realtime_blocks:plan_realtime.len() as u32,
};
let mut plan_order=Vec::with_capacity(plan_offline.len()+plan_realtime.len());
fn create_block(block:&Block,plan:Plan<Range<usize>>)->Result<Vec<u8>,BinrwError>{
let allocation_size=plan.size();
let mut buffer=Vec::with_capacity(allocation_size);
let mut cursor=std::io::Cursor::new(&mut buffer);
let block_header=plan.header();
for (range,event_type) in plan.0.into_iter().zip(EVENT_TYPES){
let num_events=range.len();
if num_events==0{
continue;
}
match event_type{
EventType::Input=>block.input_events[range].write_le(&mut cursor)?,
EventType::Output=>block.output_events[range].write_le(&mut cursor)?,
EventType::Sound=>block.sound_events[range].write_le(&mut cursor)?,
EventType::World=>block.world_events[range].write_le(&mut cursor)?,
EventType::Gravity=>block.gravity_events[range].write_le(&mut cursor)?,
EventType::Run=>block.run_events[range].write_le(&mut cursor)?,
EventType::Camera=>block.camera_events[range].write_le(&mut cursor)?,
EventType::Setting=>block.setting_events[range].write_le(&mut cursor)?,
}
}
// Allocate way too much space, whatever.
let mut output=Vec::with_capacity(allocation_size);
// Block includes header uncompressed, since the header unambiguously
// determines the size of the output data and that may be useful.
block_header.write_le(&mut std::io::Cursor::new(&mut output))?;
zstd::stream::copy_encode(buffer.as_slice(),&mut output,COMPRESSION_LEVEL)?;
Ok(output)
}
let mut blocks=Vec::with_capacity(plan_offline.len()+plan_realtime.len());
let mut block_positions=Vec::with_capacity(file_header.block_position_count() as usize);
// Fill the timelines with dummy values, we don't know the block ids yet.
// This can be done with Vec::spare_capacity_mut and unsafe, but whatever.
@@ -910,7 +944,9 @@ pub fn serialize<W:binrw::BinWriterExt>(block:&Block,writer:&mut W)->Result<(),B
let mut block_id=0;
let mut push_block=|timeline:&mut Vec<Timed<BlockId>>,planned:PlannedBlock|{
block_positions.push(BlockPosition(position));
position+=planned.plan.size() as u32;
let block=create_block(block,planned.plan).unwrap();
position+=block.len() as u32;
blocks.push(block);
// write the block id to the correct index
timeline[planned.index]=Timed{
@@ -918,8 +954,6 @@ pub fn serialize<W:binrw::BinWriterExt>(block:&Block,writer:&mut W)->Result<(),B
event:BlockId(block_id),
};
block_id+=1;
plan_order.push(planned.plan);
};
// the first block in the file is an offline block to
// initialize the state of things like the current style
@@ -960,25 +994,8 @@ pub fn serialize<W:binrw::BinWriterExt>(block:&Block,writer:&mut W)->Result<(),B
use binrw::BinWrite;
file_header.write_le(writer)?;
block_timelines.write_le(writer)?;
for plan in plan_order{
let block_header=plan.header();
block_header.write_le(writer)?;
for (range,event_type) in plan.0.into_iter().zip(EVENT_TYPES){
let num_events=range.len();
if num_events==0{
continue;
}
match event_type{
EventType::Input=>block.input_events[range].write_le(writer)?,
EventType::Output=>block.output_events[range].write_le(writer)?,
EventType::Sound=>block.sound_events[range].write_le(writer)?,
EventType::World=>block.world_events[range].write_le(writer)?,
EventType::Gravity=>block.gravity_events[range].write_le(writer)?,
EventType::Run=>block.run_events[range].write_le(writer)?,
EventType::Camera=>block.camera_events[range].write_le(writer)?,
EventType::Setting=>block.setting_events[range].write_le(writer)?,
}
}
for block in blocks{
writer.write_all(&block)?;
}
Ok(())