blf_lib_derivable/blf/
chunks.rs1use 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}