oasis_core_runtime/common/
key_format.rs1use std::{convert::TryInto, mem::size_of};
2
3use impl_trait_for_tuples::impl_for_tuples;
4
5const KEY_FORMAT_PREFIX_SIZE: usize = size_of::<u8>();
7
8pub trait KeyFormat {
11 fn prefix() -> u8;
13
14 fn size() -> usize;
16
17 fn encode_atoms(self, atoms: &mut Vec<Vec<u8>>);
19
20 fn decode_atoms(data: &[u8]) -> Self
25 where
26 Self: Sized;
27
28 fn encode_partial(self, count: usize) -> Vec<u8>
33 where
34 Self: Sized,
35 {
36 let mut v = Vec::with_capacity(KEY_FORMAT_PREFIX_SIZE + Self::size());
37 v.push(Self::prefix());
38
39 if count == 0 {
40 return v;
41 }
42
43 let mut atoms = Vec::new();
44 self.encode_atoms(&mut atoms);
45 for (included, mut atom) in atoms.into_iter().enumerate() {
46 if included >= count {
47 break;
48 }
49 v.append(&mut atom);
50 }
51
52 v
53 }
54
55 fn encode(self) -> Vec<u8>
57 where
58 Self: Sized,
59 {
60 self.encode_partial(usize::MAX)
61 }
62
63 fn decode(data: &[u8]) -> Option<Self>
68 where
69 Self: Sized,
70 {
71 assert!(!data.is_empty(), "key format: malformed input (empty data)");
72 if data[0] != Self::prefix() {
73 return None;
74 }
75 assert!(
76 data.len() >= Self::size() + KEY_FORMAT_PREFIX_SIZE,
77 "key format: malformed input"
78 );
79
80 Some(Self::decode_atoms(&data[1..]))
81 }
82}
83
84pub trait KeyFormatAtom {
86 fn size() -> usize;
87
88 fn encode_atom(self) -> Vec<u8>;
89
90 fn decode_atom(data: &[u8]) -> Self
91 where
92 Self: Sized;
93}
94
95impl KeyFormatAtom for u64 {
96 fn size() -> usize {
97 8
98 }
99
100 fn encode_atom(self) -> Vec<u8> {
101 self.to_be_bytes().to_vec()
102 }
103
104 fn decode_atom(data: &[u8]) -> Self
105 where
106 Self: Sized,
107 {
108 u64::from_be_bytes(data.try_into().expect("key_format: malformed u64 input"))
109 }
110}
111
112impl KeyFormatAtom for u8 {
113 fn size() -> usize {
114 1
115 }
116
117 fn encode_atom(self) -> Vec<u8> {
118 vec![self]
119 }
120
121 fn decode_atom(data: &[u8]) -> Self
122 where
123 Self: Sized,
124 {
125 assert!(!data.is_empty(), "key_format: malformed: u8 input");
126 data[0]
127 }
128}
129
130impl KeyFormatAtom for () {
131 fn size() -> usize {
132 0
133 }
134
135 fn encode_atom(self) -> Vec<u8> {
136 Vec::new()
137 }
138
139 fn decode_atom(_: &[u8]) {}
140}
141
142#[impl_for_tuples(2, 10)]
143impl KeyFormatAtom for Tuple {
144 fn size() -> usize {
145 for_tuples!( #( Tuple::size() )+* );
146 }
147
148 fn encode_atom(self) -> Vec<u8> {
149 let mut atoms: Vec<Vec<u8>> = [for_tuples!( #( self.Tuple.encode_atom() ),* )].to_vec();
150
151 atoms.into_iter().flatten().collect()
152 }
153
154 fn decode_atom(data: &[u8]) -> for_tuples!( ( #( Tuple ),* ) ) {
155 assert!(
156 data.len() >= Self::size(),
157 "key format atom: malformed input"
158 );
159
160 let mut sizes: Vec<usize> = [for_tuples!( #( Tuple::size() ),* )].to_vec();
161 sizes.reverse();
162 let mut data = data.to_vec();
163
164 for_tuples!(
178 (
179 #(
180 {
181 let x = Tuple::decode_atom(data.drain(0..sizes.pop().unwrap()).as_slice());
182 x
183 }
184 ),*
185 )
186 )
187 }
188}
189
190#[macro_export]
198macro_rules! key_format {
199 ($name:ident, $prefix:expr, $inner:ty) => {
200 #[derive(Debug, Default, PartialEq, Eq, Clone)]
201 struct $name($inner);
202
203 impl KeyFormat for $name {
204 fn prefix() -> u8 {
205 $prefix
206 }
207
208 fn size() -> usize {
209 <$inner>::size()
210 }
211
212 fn encode_atoms(self, atoms: &mut Vec<Vec<u8>>) {
213 atoms.push(self.0.encode_atom());
214 }
215
216 fn decode_atoms(data: &[u8]) -> Self {
217 Self(<$inner>::decode_atom(data))
218 }
219 }
220 };
221}
222
223#[cfg(test)]
224mod test {
225 use rustc_hex::ToHex;
226
227 use crate::common::crypto::hash::Hash;
228
229 use super::*;
230
231 #[derive(Debug, PartialEq)]
232 struct Test1KeyFormat {
233 h: Hash,
234 }
235
236 impl KeyFormat for Test1KeyFormat {
237 fn prefix() -> u8 {
238 b'T'
239 }
240
241 fn size() -> usize {
242 32
243 }
244
245 fn encode_atoms(self, atoms: &mut Vec<Vec<u8>>) {
246 atoms.push(self.h.as_ref().to_vec());
247 }
248
249 fn decode_atoms(data: &[u8]) -> Self {
250 Self { h: data.into() }
251 }
252 }
253
254 #[test]
255 fn test_key_format() {
256 let mut enc = Test1KeyFormat {
257 h: Hash::empty_hash(),
258 }
259 .encode();
260 assert_eq!(
261 enc.to_hex::<String>(),
262 "54c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"
263 );
264
265 let dec = Test1KeyFormat::decode(&enc);
266 assert_eq!(
267 dec,
268 Some(Test1KeyFormat {
269 h: Hash::empty_hash()
270 })
271 );
272
273 enc[0] = 0x00;
275 let dec = Test1KeyFormat::decode(&enc);
276 assert_eq!(dec, None);
277
278 let enc = Test1KeyFormat {
280 h: Hash::empty_hash(),
281 }
282 .encode_partial(0);
283 assert_eq!(enc.to_hex::<String>(), "54");
284 }
285
286 #[test]
287 fn test_key_format_atom() {
288 key_format!(TestKeyFormat, 0x01, (u8, u64, u8, u64, u64));
289
290 let key = TestKeyFormat((1, 2, 3, 4, 5));
291 let enc = key.clone().encode();
292 let dec = TestKeyFormat::decode(&enc);
293
294 assert_eq!(dec, Some(key),)
295 }
296}