write a bunch of binrw

This commit is contained in:
Quaternions 2024-01-18 19:28:01 -08:00
parent 14e7e4df29
commit d5af08730b
5 changed files with 101 additions and 43 deletions

View File

@ -1,6 +1,10 @@
use binrw::{BinReaderExt, binrw};
pub enum Error{ pub enum Error{
InvalidHeader, InvalidHeader,
InvalidSegment, InvalidSegment(binrw::Error),
InvalidSegmentId(u64),
File(crate::file::Error),
} }
/* block types /* block types
@ -28,40 +32,63 @@ loop{
*/ */
//xdd //error hiding mock code
mod simulation{ mod simulation{
#[super::binrw]
#[brw(little)]
pub struct State{} pub struct State{}
#[super::binrw]
#[brw(little)]
pub struct Instruction{} pub struct Instruction{}
} }
mod instruction{ mod instruction{
pub struct TimedInstruction<Instruction>{instruction:Instruction} #[super::binrw]
#[brw(little)]
pub struct TimedInstruction<Instruction:binrw::BinRead+binrw::BinWrite>{
time:u64,
instruction:Instruction
}
} }
mod timeline{ mod timeline{
pub struct Timeline<Instruction>{timeline:Vec<super::instruction::TimedInstruction<Instruction>>} #[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 //serious code
#[binrw]
#[brw(little)]
struct SegmentId(u64); struct SegmentId(u64);
#[binrw]
#[brw(little)]
pub struct Segment{ pub struct Segment{
state:simulation::State, state:simulation::State,
#[bw(try_calc(u32::try_from(instructions.len())))]
instruction_count:u32,
#[br(count=instruction_count)]
instructions:Vec<instruction::TimedInstruction<simulation::Instruction>> instructions:Vec<instruction::TimedInstruction<simulation::Instruction>>
} }
pub struct StreamableBot{ pub struct StreamableBot<R:BinReaderExt>{
file:crate::file::File, file:crate::file::File<R>,
timeline:timeline::Timeline<SegmentId>, timeline:timeline::Timeline<SegmentId>,
segment_id_to_block_id:Vec<crate::file::BlockId>,
} }
impl StreamableBot{ impl<R:BinReaderExt> StreamableBot<R>{
pub fn new(file:crate::file::File)->Result<Self,Error>{ pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{
Err(Error::InvalidHeader) Err(Error::InvalidHeader)
} }
pub fn load_segment(&mut self,segment_id:u64)->Result<Segment,Error>{ pub fn load_segment(&mut self,segment_id:SegmentId)->Result<Segment,Error>{
//load region from disk let block_id=*self.segment_id_to_block_id.get(segment_id.0 as usize).ok_or(Error::InvalidSegmentId(segment_id.0))?;
//parse the models and determine what resources need to be loaded let mut block=self.file.take_block(block_id).map_err(|e|Error::File(e))?;
//load resources into self.resources let segment=block.read_le().map_err(|e|Error::InvalidSegment(e))?;
//return Region Ok(segment)
Err(Error::InvalidSegment)
} }
} }

View File

@ -1,3 +1,5 @@
use binrw::BinReaderExt;
pub enum Error{ pub enum Error{
InvalidHeader, InvalidHeader,
} }
@ -17,12 +19,12 @@ how to do worldstate for deathrun!?
*/ */
pub struct StreamableDemo{ pub struct StreamableDemo<R:BinReaderExt>{
map:Box<crate::map::StreamableMap>, map:Box<crate::map::StreamableMap<R>>,
bots:Vec<crate::bot::StreamableBot>, bots:Vec<crate::bot::StreamableBot<R>>,
} }
impl StreamableDemo{ impl<R:BinReaderExt> StreamableDemo<R>{
pub fn new(file:crate::file::File)->Result<Self,Error>{ pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{
Err(Error::InvalidHeader) Err(Error::InvalidHeader)
} }
} }

View File

@ -1,10 +1,12 @@
//file format "sniff" //file format "sniff"
use binrw::{binrw, BinReaderExt}; use binrw::{binrw, BinReaderExt, io::TakeSeekExt};
pub enum Error{ pub enum Error{
InvalidHeader(binrw::Error), InvalidHeader(binrw::Error),
UnexpectedEOF, UnexpectedEOF,
InvalidBlockId(usize),
Seek(std::io::Error),
} }
/* spec /* spec
@ -56,26 +58,35 @@ struct Header{
priming:u64, priming:u64,
/// uuid for this file /// uuid for this file
resource:u128, resource:u128,
#[bw(try_calc(u64::try_from(block_location.len())))] #[bw(try_calc(u64::try_from(block_location.len()-1)))]
block_count:u64, block_count:u64,
#[br(count=block_count)] #[br(count=block_count+1)]
block_location:Vec<u64>, block_location:Vec<u64>,
} }
pub struct BlockId(usize);
pub(crate) struct File{ pub(crate) struct File<R:BinReaderExt>{
header:Header, header:Header,
//reference to the data //reference to the data
data:R,
} }
impl File{ impl<R:BinReaderExt> File<R>{
pub(crate) fn new<R:BinReaderExt>(mut input:R)->Result<Self,Error>{ pub(crate) fn new(mut input:R)->Result<File<R>,Error>{
Ok(Self{ Ok(File{
header:input.read_le().map_err(|e|Error::InvalidHeader(e))?, header:input.read_le().map_err(|e|Error::InvalidHeader(e))?,
data:input,
}) })
} }
pub(crate) fn read_block(&mut self,block_id:u64)->Result<Vec<u8>,Error>{ pub(crate) fn take_block(&mut self,block_id:BlockId)->Result<binrw::io::TakeSeek<&mut R>,Error>{
Err(Error::UnexpectedEOF) if self.header.block_location.len()<=block_id.0{
return Err(Error::InvalidBlockId(block_id.0))
}
let block_start=self.header.block_location[block_id.0];
let block_end=self.header.block_location[block_id.0+1];
self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(|e|Error::Seek(e))?;
Ok((&mut self.data).take_seek(block_end-block_start))
} }
pub(crate) fn fourcc(&self)->FourCC{ pub(crate) fn fourcc(&self)->FourCC{
self.header.fourcc self.header.fourcc

View File

@ -13,13 +13,13 @@ pub enum Error{
Demo(demo::Error), Demo(demo::Error),
} }
pub enum SNF{ pub enum SNF<R:BinReaderExt>{
Map(map::StreamableMap), Map(map::StreamableMap<R>),
Bot(bot::StreamableBot), Bot(bot::StreamableBot<R>),
Demo(demo::StreamableDemo), Demo(demo::StreamableDemo<R>),
} }
pub fn read_snf<R:BinReaderExt>(input:R)->Result<SNF,Error>{ pub fn read_snf<R:BinReaderExt>(input:R)->Result<SNF<R>,Error>{
let file=file::File::new(input).map_err(|e|Error::Header(e))?; let file=file::File::new(input).map_err(|e|Error::Header(e))?;
Ok(match file.fourcc(){ Ok(match file.fourcc(){
file::FourCC::Map=>SNF::Map(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), file::FourCC::Map=>SNF::Map(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?),
@ -27,21 +27,21 @@ pub fn read_snf<R:BinReaderExt>(input:R)->Result<SNF,Error>{
file::FourCC::Demo=>SNF::Demo(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), file::FourCC::Demo=>SNF::Demo(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?),
}) })
} }
pub fn read_map<R:BinReaderExt>(input:R)->Result<map::StreamableMap,Error>{ pub fn read_map<R:BinReaderExt>(input:R)->Result<map::StreamableMap<R>,Error>{
let file=file::File::new(input).map_err(|e|Error::Header(e))?; let file=file::File::new(input).map_err(|e|Error::Header(e))?;
match file.fourcc(){ match file.fourcc(){
file::FourCC::Map=>Ok(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?), file::FourCC::Map=>Ok(map::StreamableMap::new(file).map_err(|e|Error::Map(e))?),
_=>Err(Error::UnexpectedFourCC) _=>Err(Error::UnexpectedFourCC)
} }
} }
pub fn read_bot<R:BinReaderExt>(input:R)->Result<bot::StreamableBot,Error>{ pub fn read_bot<R:BinReaderExt>(input:R)->Result<bot::StreamableBot<R>,Error>{
let file=file::File::new(input).map_err(|e|Error::Header(e))?; let file=file::File::new(input).map_err(|e|Error::Header(e))?;
match file.fourcc(){ match file.fourcc(){
file::FourCC::Bot=>Ok(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?), file::FourCC::Bot=>Ok(bot::StreamableBot::new(file).map_err(|e|Error::Bot(e))?),
_=>Err(Error::UnexpectedFourCC) _=>Err(Error::UnexpectedFourCC)
} }
} }
pub fn read_demo<R:BinReaderExt>(input:R)->Result<demo::StreamableDemo,Error>{ pub fn read_demo<R:BinReaderExt>(input:R)->Result<demo::StreamableDemo<R>,Error>{
let file=file::File::new(input).map_err(|e|Error::Header(e))?; let file=file::File::new(input).map_err(|e|Error::Header(e))?;
match file.fourcc(){ match file.fourcc(){
file::FourCC::Demo=>Ok(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?), file::FourCC::Demo=>Ok(demo::StreamableDemo::new(file).map_err(|e|Error::Demo(e))?),

View File

@ -1,6 +1,10 @@
use binrw::{BinReaderExt, binrw};
pub enum Error{ pub enum Error{
InvalidHeader, InvalidHeader,
InvalidNode, InvalidNodeId(u64),
InvalidRegion(binrw::Error),
File(crate::file::Error),
} }
/* block types /* block types
@ -53,12 +57,14 @@ for model_id in 0..num_models{
*/ */
//xdd //error hiding mock code
mod physics{ mod physics{
pub struct StyleModifiers{} pub struct StyleModifiers{}
} }
mod model{ mod model{
pub struct IndexedModel{} pub struct IndexedModel{}
#[super::binrw]
#[brw(little)]
pub struct ModelInstance{} pub struct ModelInstance{}
} }
mod image{ mod image{
@ -73,17 +79,26 @@ pub struct BvhNodeId(u64);
struct BvhNode{ struct BvhNode{
// //
} }
#[binrw]
#[brw(little)]
struct Region{
#[bw(try_calc(u32::try_from(models.len())))]
model_count:u32,
#[br(count=model_count)]
models:Vec<model::ModelInstance>,
}
pub struct StreamableMap{ pub struct StreamableMap<R:BinReaderExt>{
file:crate::file::File, file:crate::file::File<R>,
style:physics::StyleModifiers,//probably should move this out of physics style:physics::StyleModifiers,//probably should move this out of physics
bvh:BvhNode, bvh:BvhNode,
node_id_to_block_id:Vec<crate::file::BlockId>,
//do not need this? return only new data with load_node //do not need this? return only new data with load_node
resource_model:std::collections::HashMap<ModelUuid,model::IndexedModel>, resource_model:std::collections::HashMap<ModelUuid,model::IndexedModel>,
resource_image:std::collections::HashMap<ImageUuid,image::Image>, resource_image:std::collections::HashMap<ImageUuid,image::Image>,
} }
impl StreamableMap{ impl<R:BinReaderExt> StreamableMap<R>{
pub fn new(file:crate::file::File)->Result<Self,Error>{ pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{
Err(Error::InvalidHeader) Err(Error::InvalidHeader)
} }
pub fn load_node(&mut self,node_id:BvhNodeId)->Result<Vec<model::ModelInstance>,Error>{ pub fn load_node(&mut self,node_id:BvhNodeId)->Result<Vec<model::ModelInstance>,Error>{
@ -91,6 +106,9 @@ impl StreamableMap{
//parse the models and determine what resources need to be loaded //parse the models and determine what resources need to be loaded
//load resources into self.resources //load resources into self.resources
//return Region //return Region
Err(Error::InvalidNode) let block_id=*self.node_id_to_block_id.get(node_id.0 as usize).ok_or(Error::InvalidNodeId(node_id.0))?;
let mut block=self.file.take_block(block_id).map_err(|e|Error::File(e))?;
let region:Region=block.read_le().map_err(|e|Error::InvalidRegion(e))?;
Ok(region.models)
} }
} }