strafe-client-jed/src/file.rs

98 lines
2.2 KiB
Rust
Raw Normal View History

2024-01-16 03:09:34 +00:00
//file format "sniff"
2024-01-19 03:28:01 +00:00
use binrw::{binrw, BinReaderExt, io::TakeSeekExt};
2024-01-19 00:59:00 +00:00
2024-01-16 03:09:34 +00:00
pub enum Error{
2024-01-19 00:59:00 +00:00
InvalidHeader(binrw::Error),
2024-01-16 03:30:26 +00:00
UnexpectedEOF,
InvalidBlockId(BlockId),
2024-01-19 03:28:01 +00:00
Seek(std::io::Error),
2024-01-16 03:09:34 +00:00
}
/* spec
//begin global header
//global metadata (32 bytes)
b"SNFB"
u32 format_version
u64 priming_bytes
//how many bytes of the file must be read to guarantee all of the expected
//format-specific metadata is available to facilitate streaming the remaining contents
//used by the database to guarantee that it serves at least the bare minimum
u128 resource_uuid
//identifies the file from anywhere for any other file
//global block layout (variable size)
u64 num_blocks
for block_id in 0..num_blocks{
u64 first_byte
}
//end global header
//begin blocks
//each block is compressed with zstd or gz or something
*/
2024-01-19 00:59:00 +00:00
#[binrw]
#[brw(little)]
2024-01-19 00:39:58 +00:00
#[derive(Clone,Copy)]
pub(crate) enum FourCC{
2024-01-19 00:59:00 +00:00
#[brw(magic=b"SNFM")]
2024-01-19 00:39:58 +00:00
Map,
2024-01-19 00:59:00 +00:00
#[brw(magic=b"SNFB")]
2024-01-19 00:39:58 +00:00
Bot,
2024-01-19 00:59:00 +00:00
#[brw(magic=b"SNFD")]
2024-01-19 00:39:58 +00:00
Demo,
2024-01-16 03:09:34 +00:00
}
2024-01-19 00:59:00 +00:00
#[binrw]
#[brw(little)]
2024-01-19 00:39:58 +00:00
struct Header{
2024-01-16 03:09:34 +00:00
/// Type of file
2024-01-19 00:39:58 +00:00
fourcc:FourCC,
2024-01-16 03:09:34 +00:00
/// Type version
version:u32,
/// Minimum data required to know the location of all streamable resources for this specific file
priming:u64,
/// uuid for this file
resource:u128,
#[bw(try_calc(u32::try_from(block_location.len()-1)))]
block_count:u32,
2024-01-19 03:28:01 +00:00
#[br(count=block_count+1)]
2024-01-19 00:59:00 +00:00
block_location:Vec<u64>,
2024-01-16 03:09:34 +00:00
}
#[binrw]
#[brw(little)]
#[derive(Clone,Copy,Hash,id::Id,Eq,PartialEq)]
pub struct BlockId(u32);
2024-01-17 04:07:11 +00:00
2024-01-19 03:28:01 +00:00
pub(crate) struct File<R:BinReaderExt>{
2024-01-19 00:39:58 +00:00
header:Header,
//reference to the data
2024-01-19 03:28:01 +00:00
data:R,
2024-01-19 00:39:58 +00:00
}
2024-01-19 03:28:01 +00:00
impl<R:BinReaderExt> File<R>{
pub(crate) fn new(mut input:R)->Result<File<R>,Error>{
Ok(File{
header:input.read_le().map_err(Error::InvalidHeader)?,
2024-01-19 03:28:01 +00:00
data:input,
2024-01-19 00:59:00 +00:00
})
2024-01-19 00:39:58 +00:00
}
2024-01-19 03:28:01 +00:00
pub(crate) fn take_block(&mut self,block_id:BlockId)->Result<binrw::io::TakeSeek<&mut R>,Error>{
if self.header.block_location.len() as u32<=block_id.get(){
return Err(Error::InvalidBlockId(block_id))
2024-01-19 03:28:01 +00:00
}
let block_start=self.header.block_location[block_id.get() as usize];
let block_end=self.header.block_location[block_id.get() as usize+1];
self.data.seek(std::io::SeekFrom::Start(block_start)).map_err(Error::Seek)?;
2024-01-19 03:28:01 +00:00
Ok((&mut self.data).take_seek(block_end-block_start))
2024-01-19 00:39:58 +00:00
}
pub(crate) fn fourcc(&self)->FourCC{
self.header.fourcc
}
2024-01-17 04:07:11 +00:00
}