blf_lib_derivable/blf/
chunks.rs

1use std::any::Any;
2use binrw::{BinRead, BinWrite, BinWriterExt};
3use crate::blf::s_blf_header::s_blf_header;
4use crate::types::chunk_signature::chunk_signature;
5use crate::types::chunk_version::chunk_version;
6
7pub trait BlfChunk {
8    fn get_signature() -> chunk_signature;
9    fn get_version() -> chunk_version;
10}
11
12pub trait DynamicBlfChunk {
13    fn signature(&self) -> chunk_signature;
14    fn version(&self) -> chunk_version;
15}
16
17pub trait BlfChunkHooks {
18    fn before_write(&mut self, _previously_written: &Vec<u8>) {}
19    fn after_read(&mut self) {}
20}
21
22pub trait SerializableBlfChunk: DynamicBlfChunk + Any + Send + Sync {
23    fn encode_body(&mut self, previously_written: &Vec<u8>) -> Vec<u8>;
24    fn decode_body(&mut self, buffer: &[u8]);
25
26    fn write(&mut self, previously_written: &Vec<u8>) -> Vec<u8> {
27        let mut encoded_chunk = self.encode_body(previously_written);
28        let header = s_blf_header {
29            signature: self.signature(),
30            version: self.version(),
31            chunk_size: (encoded_chunk.len() + s_blf_header::size()) as u32,
32        };
33
34        let mut encoded = Vec::with_capacity(s_blf_header::size() + encoded_chunk.len());
35        encoded.append(&mut header.encode());
36        encoded.append(&mut encoded_chunk);
37
38        encoded
39    }
40
41    fn as_any(&self) -> &dyn Any;
42}
43
44impl<T: DynamicBlfChunk + BinRead + BinWrite + Clone + Any + BlfChunkHooks + Send + Sync> SerializableBlfChunk for T
45    where for<'a> <T as BinWrite>::Args<'a>: Default, for<'a> <T as BinRead>::Args<'a>: Default {
46    fn encode_body(&mut self, previously_written: &Vec<u8>) -> Vec<u8> where for<'a> <T as BinWrite>::Args<'a>: Default {
47        self.before_write(previously_written);
48
49        let mut writer = std::io::Cursor::new(Vec::<u8>::new());
50        writer.write_ne(self).unwrap();
51        writer.get_ref().clone()
52    }
53
54    fn decode_body(&mut self, buffer: &[u8]) where for<'b> <T as BinRead>::Args<'b>: Default {
55        let mut reader = std::io::Cursor::new(buffer);
56
57        self.clone_from(&T::read_ne(&mut reader).unwrap());
58
59        self.after_read();
60    }
61
62    fn as_any(&self) -> &dyn Any {
63        self
64    }
65}
66
67pub trait ReadableBlfChunk: BlfChunk + Sized + SerializableBlfChunk + Default {
68    fn read(buffer: Vec<u8>, header: Option<s_blf_header>) -> Self {
69        let offset = if header.is_some() { 0 } else { s_blf_header::size() };
70        let header = header.unwrap_or_else(|| s_blf_header::decode(&buffer.as_slice()) );
71        let end = (header.chunk_size as usize - s_blf_header::size()) - offset;
72        let mut chunk = Self::default();
73        chunk.decode_body(&buffer[offset..end]);
74        chunk
75    }
76}
77
78impl<T: BlfChunk + Sized + SerializableBlfChunk + Default> ReadableBlfChunk for T {
79
80}
81
82pub trait TitleAndBuild {
83    fn get_title() -> &'static str;
84
85    fn get_build_string() -> &'static str;
86}
87
88pub trait DynTitleAndBuild {
89    fn title(&self) -> String;
90
91    fn build_string(&self) -> String;
92}
93
94pub trait ChunkFactory {
95    fn decode(&self, signature: chunk_signature, version: chunk_version, buffer: Vec<u8>) -> Result<Box<dyn SerializableBlfChunk>, &str>;
96}