1pub mod tools;
2pub mod v1;
3pub mod v2;
4pub mod v3;
5pub mod v4;
6pub mod v5;
7pub mod v6;
8
9use type_equalities::{IsEqual, trivial_eq};
10
11use crate::tools::hash_vec;
12
13pub trait Track
14where
15 Self::Metadata: IsEqual<<<<Self::Part as Part>::Block as Block>::Track as Track>::Metadata>,
19{
20 type Part: Part;
21
22 type Metadata: Copy;
23 fn meta(&self) -> Self::Metadata;
24 fn parts(&self) -> Vec<Self::Part>;
25
26 fn decode_meta(data: &[u8], offset: &mut usize) -> Option<Self::Metadata>;
27 fn encode_meta(&self, data: &mut Vec<u8>);
28 fn from_data(metadata: Self::Metadata, parts: Vec<Self::Part>) -> Self;
29
30 type TrackInfo;
31 fn decode_track_code(
32 track_code: &str,
33 ) -> Option<(
34 String,
35 Self::TrackInfo,
36 Vec<u8>,
37 )>;
38 fn encode_track_code(name: String, info: Self::TrackInfo, track_data: &[u8]) -> Option<String>;
39}
40pub trait Part: Sized {
41 type Block: Block;
42
43 fn id(&self) -> u8;
46 fn amount(&self) -> u32;
47 fn blocks(&self) -> Vec<Self::Block>;
48 fn from_data(id: u8, amount: u32, blocks: Vec<Self::Block>) -> Self;
49
50 fn decode_header(data: &[u8], offset: &mut usize) -> Option<(u8, u32)>;
51 fn encode_header(&self, data: &mut Vec<u8>);
52 fn decode(
53 data: &[u8],
54 offset: &mut usize,
55 meta: <<Self::Block as Block>::Track as Track>::Metadata,
56 ) -> Option<Self> {
57 let (id, amount) = Self::decode_header(data, offset)?;
58 let mut blocks = Vec::new();
59 for _ in 0..amount {
60 blocks.push(Self::Block::decode(data, offset, id, meta)?);
61 }
62 Some(Self::from_data(id, amount, blocks))
63 }
64 fn encode(&self, data: &mut Vec<u8>, meta: <<Self::Block as Block>::Track as Track>::Metadata) {
65 self.encode_header(data);
66 for block in &self.blocks() {
67 block.encode(data, meta);
68 }
69 }
70}
71pub trait Block: Sized {
72 type Track: Track;
73
74 type Extra;
75 fn extra_data(&self) -> Self::Extra;
76
77 type Coord;
79 fn pos(&self) -> (Self::Coord, Self::Coord, Self::Coord);
80 fn rot(&self) -> u8;
81
82 fn decode(
83 data: &[u8],
84 offset: &mut usize,
85 id: u8,
86 meta: <Self::Track as Track>::Metadata,
87 ) -> Option<Self>;
88 fn encode(&self, data: &mut Vec<u8>, meta: <Self::Track as Track>::Metadata);
89}
90
91pub fn decode_track_data<T: Track>(data: &[u8]) -> Option<T> {
92 let mut offset = 0;
93 let meta = T::decode_meta(data, &mut offset)?;
95 let mut parts = Vec::new();
96 while offset < data.len() {
97 parts.push(T::Part::decode(
98 data,
99 &mut offset,
100 trivial_eq::<
101 _,
103 <<<T::Part as Part>::Block as Block>::Track as Track>::Metadata,
104 >()
105 .coerce(meta),
106 )?);
107 }
108
109 Some(T::from_data(meta, parts))
110}
111pub fn encode_track_data<T: Track>(track: &T) -> Vec<u8> {
112 let mut data = Vec::new();
113 let meta = track.meta();
114
115 track.encode_meta(&mut data);
117 for part in track.parts() {
118 part.encode(
119 &mut data,
120 trivial_eq::<
121 _,
123 <<<T::Part as Part>::Block as Block>::Track as Track>::Metadata,
124 >()
125 .coerce(meta),
126 );
127 }
128
129 data
130}
131pub fn export_to_id<T: Track>(track_code: &str) -> Option<String> {
132 let (_, _, track_data) = T::decode_track_code(track_code)?;
133 let id = hash_vec(track_data);
134 Some(id)
135}