ic_stable_structures/storable/
tuples.rs1use crate::storable::{
2 bounds, bytes_to_store_size, bytes_to_store_size_bounded, Bound, Bounds, Storable,
3};
4use std::borrow::Cow;
5
6impl<A, B> Storable for (A, B)
7where
8 A: Storable,
9 B: Storable,
10{
11 fn to_bytes(&self) -> Cow<'_, [u8]> {
12 Cow::Owned(into_bytes_inner_2(Self::BOUND, &self.0, &self.1))
13 }
14
15 fn into_bytes(self) -> Vec<u8> {
16 into_bytes_inner_2(Self::BOUND, &self.0, &self.1)
17 }
18
19 #[inline]
20 fn from_bytes(bytes: Cow<[u8]>) -> Self {
21 match Self::BOUND {
22 Bound::Bounded { max_size, .. } => {
23 assert_eq!(bytes.len(), max_size as usize);
24 let a_bounds = bounds::<A>();
25 let b_bounds = bounds::<B>();
26 let a_max_size = a_bounds.max_size as usize;
27 let b_max_size = b_bounds.max_size as usize;
28 let sizes_offset = a_max_size + b_max_size;
29 let a_size_len = bytes_to_store_size_bounded(&a_bounds) as usize;
30 let b_size_len = bytes_to_store_size_bounded(&b_bounds) as usize;
31
32 let a_len = decode_size_of_bound(
33 &bytes[sizes_offset..sizes_offset + a_size_len],
34 &a_bounds,
35 );
36 let b_len = decode_size_of_bound(
37 &bytes[sizes_offset + a_size_len..sizes_offset + a_size_len + b_size_len],
38 &b_bounds,
39 );
40
41 let a = A::from_bytes(Cow::Borrowed(&bytes[..a_len]));
42 let b = B::from_bytes(Cow::Borrowed(&bytes[a_max_size..a_max_size + b_len]));
43 (a, b)
44 }
45 _ => todo!("Deserializing tuples with unbounded types is not yet supported."),
46 }
47 }
48
49 const BOUND: Bound = match (A::BOUND, B::BOUND) {
50 (Bound::Bounded { .. }, Bound::Bounded { .. }) => {
51 let a_bounds = bounds::<A>();
52 let b_bounds = bounds::<B>();
53 Bound::Bounded {
54 max_size: a_bounds.max_size
55 + b_bounds.max_size
56 + bytes_to_store_size_bounded(&a_bounds)
57 + bytes_to_store_size_bounded(&b_bounds),
58 is_fixed_size: a_bounds.is_fixed_size && b_bounds.is_fixed_size,
59 }
60 }
61 _ => Bound::Unbounded,
62 };
63}
64
65#[inline]
66fn into_bytes_inner_2<A, B>(bound: Bound, a: &A, b: &B) -> Vec<u8>
67where
68 A: Storable,
69 B: Storable,
70{
71 match bound {
72 Bound::Bounded { max_size, .. } => {
73 let a_bytes = a.to_bytes();
74 let b_bytes = b.to_bytes();
75 let a_bounds = bounds::<A>();
76 let b_bounds = bounds::<B>();
77 let a_max_size = a_bounds.max_size as usize;
78 let b_max_size = b_bounds.max_size as usize;
79 let a_size_len = bytes_to_store_size_bounded(&a_bounds) as usize;
80 let b_size_len = bytes_to_store_size_bounded(&b_bounds) as usize;
81 let sizes_offset = a_max_size + b_max_size;
82
83 debug_assert!(a_bytes.len() <= a_max_size);
84 debug_assert!(b_bytes.len() <= b_max_size);
85
86 let mut bytes = vec![0; max_size as usize];
87 bytes[..a_bytes.len()].copy_from_slice(a_bytes.as_ref());
88 bytes[a_max_size..a_max_size + b_bytes.len()].copy_from_slice(b_bytes.as_ref());
89
90 encode_size_of_bound(
91 &mut bytes[sizes_offset..sizes_offset + a_size_len],
92 a_bytes.len(),
93 &a_bounds,
94 );
95 encode_size_of_bound(
96 &mut bytes[sizes_offset + a_size_len..sizes_offset + a_size_len + b_size_len],
97 b_bytes.len(),
98 &b_bounds,
99 );
100
101 bytes
102 }
103 _ => todo!("Serializing tuples with unbounded types is not yet supported."),
104 }
105}
106
107fn decode_size_of_bound(src: &[u8], bounds: &Bounds) -> usize {
108 if bounds.is_fixed_size {
109 bounds.max_size as usize
110 } else {
111 decode_size(src, bytes_to_store_size(bounds.max_size as usize))
112 }
113}
114
115fn encode_size_of_bound(dst: &mut [u8], n: usize, bounds: &Bounds) {
116 if !bounds.is_fixed_size {
117 encode_size(dst, n, bytes_to_store_size(bounds.max_size as usize));
118 }
119}
120
121fn decode_size(src: &[u8], size_len: usize) -> usize {
123 match size_len {
124 1 => src[0] as usize,
125 2 => u16::from_be_bytes([src[0], src[1]]) as usize,
126 _ => u32::from_be_bytes([src[0], src[1], src[2], src[3]]) as usize,
127 }
128}
129
130fn encode_size(dst: &mut [u8], size_len: usize, bytes: usize) {
132 match bytes {
133 1 => dst[0] = size_len as u8,
134 2 => dst[..2].copy_from_slice(&(size_len as u16).to_be_bytes()),
135 _ => dst[..4].copy_from_slice(&(size_len as u32).to_be_bytes()),
136 }
137}
138
139fn encode_size_lengths(sizes: &[usize]) -> u8 {
140 assert!(sizes.len() <= 4);
141
142 let mut size_lengths_byte: u8 = 0;
143
144 for size in sizes.iter() {
145 let size_length = bytes_to_store_size(*size);
146 size_lengths_byte <<= 2;
149 size_lengths_byte += (size_length - 1) as u8;
152 }
153
154 size_lengths_byte
155}
156
157fn decode_size_lengths(mut encoded_bytes_to_store: u8, number_of_encoded_lengths: u8) -> Vec<u8> {
158 assert!(number_of_encoded_lengths <= 4);
159
160 let mut bytes_to_store_sizes = vec![];
161
162 for _ in 0..number_of_encoded_lengths {
163 let mask: u8 = 3;
167 let bytes_to_store: u8 = (encoded_bytes_to_store & mask) + 1;
172 bytes_to_store_sizes.push(bytes_to_store);
173 encoded_bytes_to_store >>= 2;
174 }
175
176 bytes_to_store_sizes.reverse();
180
181 bytes_to_store_sizes
182}
183
184fn encode_tuple_element<T: Storable>(dst: &mut [u8], bytes: &[u8], last: bool) -> usize {
188 let mut offset = 0;
189 if !last && !T::BOUND.is_fixed_size() {
190 let size_len = bytes_to_store_size(bytes.len());
191 encode_size(&mut dst[offset..], bytes.len(), size_len);
192 offset += size_len;
193 }
194 dst[offset..offset + bytes.len()].copy_from_slice(bytes);
195 offset + bytes.len()
196}
197
198fn decode_tuple_element<T: Storable>(src: &[u8], size_len: Option<u8>, last: bool) -> (T, usize) {
205 let mut read = 0;
206 let size = if let Some(len) = size_len {
207 let s = decode_size(&src[read..], len as usize);
208 read += len as usize;
209 s
210 } else if let Bound::Bounded {
211 max_size,
212 is_fixed_size: true,
213 } = T::BOUND
214 {
215 max_size as usize
216 } else {
217 assert!(last);
219 src.len()
220 };
221 (
222 T::from_bytes(Cow::Borrowed(&src[read..read + size])),
223 read + size,
224 )
225}
226
227const fn sizes_overhead<A: Storable, B: Storable>(a_size: usize, b_size: usize) -> usize {
229 let mut sizes_overhead = 0;
230
231 if !(A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size()) {
232 sizes_overhead += 1;
234
235 if !A::BOUND.is_fixed_size() {
236 sizes_overhead += bytes_to_store_size(a_size);
237 }
238
239 if !B::BOUND.is_fixed_size() {
240 sizes_overhead += bytes_to_store_size(b_size);
241 }
242 }
243
244 sizes_overhead
245}
246
247impl<A, B, C> Storable for (A, B, C)
248where
249 A: Storable,
250 B: Storable,
251 C: Storable,
252{
253 fn to_bytes(&self) -> Cow<'_, [u8]> {
259 Cow::Owned(into_bytes_inner_3(&self.0, &self.1, &self.2))
260 }
261
262 fn into_bytes(self) -> Vec<u8> {
263 into_bytes_inner_3(&self.0, &self.1, &self.2)
264 }
265
266 #[inline]
267 fn from_bytes(bytes: Cow<[u8]>) -> Self {
268 let mut offset = 0;
269 let mut size_lengths = [None, None];
270
271 if !(A::BOUND.is_fixed_size() && B::BOUND.is_fixed_size()) {
272 let lengths = decode_size_lengths(bytes[0], 2);
273 offset += 1;
274 if !A::BOUND.is_fixed_size() {
275 size_lengths[0] = Some(lengths[0]);
276 }
277 if !B::BOUND.is_fixed_size() {
278 size_lengths[1] = Some(lengths[1]);
279 }
280 }
281
282 let (a, read) = decode_tuple_element::<A>(&bytes[offset..], size_lengths[0], false);
283 offset += read;
284 let (b, read) = decode_tuple_element::<B>(&bytes[offset..], size_lengths[1], false);
285 offset += read;
286 let (c, read) = decode_tuple_element::<C>(&bytes[offset..], None, true);
287 offset += read;
288
289 debug_assert_eq!(offset, bytes.len());
290 (a, b, c)
291 }
292
293 const BOUND: Bound = match (A::BOUND, B::BOUND, C::BOUND) {
294 (Bound::Bounded { .. }, Bound::Bounded { .. }, Bound::Bounded { .. }) => {
295 let a_bounds = bounds::<A>();
296 let b_bounds = bounds::<B>();
297 let c_bounds = bounds::<C>();
298 let sizes_overhead =
299 sizes_overhead::<A, B>(a_bounds.max_size as usize, b_bounds.max_size as usize)
300 as u32;
301 Bound::Bounded {
302 max_size: a_bounds.max_size
303 + b_bounds.max_size
304 + c_bounds.max_size
305 + sizes_overhead,
306 is_fixed_size: a_bounds.is_fixed_size
307 && b_bounds.is_fixed_size
308 && c_bounds.is_fixed_size,
309 }
310 }
311 _ => Bound::Unbounded,
312 };
313}
314
315#[inline]
316fn into_bytes_inner_3<A, B, C>(a: &A, b: &B, c: &C) -> Vec<u8>
317where
318 A: Storable,
319 B: Storable,
320 C: Storable,
321{
322 let a_bytes = a.to_bytes();
323 let b_bytes = b.to_bytes();
324 let c_bytes = c.to_bytes();
325 let a_size = a_bytes.len();
326 let b_size = b_bytes.len();
327 let c_size = c_bytes.len();
328
329 let sizes_overhead = sizes_overhead::<A, B>(a_size, b_size);
330 let output_size = a_size + b_size + c_size + sizes_overhead;
331 let mut bytes = vec![0; output_size];
332 let mut offset = 0;
333
334 if sizes_overhead != 0 {
335 bytes[offset] = encode_size_lengths(&[a_size, b_size]);
336 offset += 1;
337 }
338
339 offset += encode_tuple_element::<A>(&mut bytes[offset..], a_bytes.as_ref(), false);
340 offset += encode_tuple_element::<B>(&mut bytes[offset..], b_bytes.as_ref(), false);
341 offset += encode_tuple_element::<C>(&mut bytes[offset..], c_bytes.as_ref(), true);
342
343 debug_assert_eq!(offset, output_size);
344 bytes
345}