use binrw::{BinReaderExt, binrw}; pub enum Error{ InvalidHeader, InvalidSegment(binrw::Error), InvalidSegmentId(SegmentId), File(crate::file::Error), } /* block types BLOCK_BOT_HEADER: u128 map_resource_uuid //which map is this bot running //don't include style info in bot header because it's in the simulation state //blocks are laid out in chronological order, but indices may jump around. u64 num_segments for _ in 0..num_segments{ i64 time //simulation_state timestamp u64 block_id } BLOCK_BOT_SEGMENT: //format version indicates what version of these structures to use SimulationState simulation_state //SimulationState is just under ClientState which includes Play/Pause events that the simulation doesn't know about. //to read, greedily decode instructions until eof loop{ //delta encode as much as possible (time,mousepos) //strafe ticks are implied //physics can be implied in an input-only bot file TimedInstruction<SimulationInstruction> instruction } */ //error hiding mock code mod simulation{ #[super::binrw] #[brw(little)] pub struct State{} #[super::binrw] #[brw(little)] pub struct Instruction{} } // mod instruction{ // #[super::binrw] // #[brw(little)] // pub struct TimedInstruction<Instruction:binrw::BinRead+binrw::BinWrite>{ // time:u64, // instruction:Instruction // } // } // mod timeline{ // #[super::binrw] // #[brw(little)] // pub struct Timeline<Instruction:binrw::BinRead+binrw::BinWrite>{ // #[bw(try_calc(u32::try_from(instructions.len())))] // instruction_count:u32, // #[br(count=instruction_count)] // instructions:Vec<super::instruction::TimedInstruction<Instruction>> // } // } //serious code #[binrw] #[brw(little)] #[derive(Clone,Copy,id::Id)] pub struct SegmentId(u32); #[binrw] #[brw(little)] pub struct Segment{ state:simulation::State, //#[bw(try_calc(u32::try_from(instructions.len())))] //instruction_count:u32, //#[br(count=instruction_count)] //instructions:Vec<instruction::TimedInstruction<simulation::Instruction>> } pub struct StreamableBot<R:BinReaderExt>{ file:crate::file::File<R>, //timeline:timeline::Timeline<SegmentId>, segment_id_to_block_id:Vec<crate::file::BlockId>, } impl<R:BinReaderExt> StreamableBot<R>{ pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{ Err(Error::InvalidHeader) } pub fn load_segment(&mut self,segment_id:SegmentId)->Result<Segment,Error>{ let block_id=*self.segment_id_to_block_id.get(segment_id.get() as usize).ok_or(Error::InvalidSegmentId(segment_id))?; let mut block=self.file.take_block(block_id).map_err(Error::File)?; let segment=block.read_le().map_err(Error::InvalidSegment)?; Ok(segment) } }