diff --git a/server/src/storage/mod.rs b/server/src/storage/mod.rs index 9f53f5a3..98c4e7d2 100644 --- a/server/src/storage/mod.rs +++ b/server/src/storage/mod.rs @@ -485,6 +485,78 @@ mod de { } } + pub fn deserialize_list_map(bytes: &[u8]) -> Option>> { + if bytes.len() < 8 { + // 8B extent not here + return None; + } + // now let's read in the extent + unsafe { + let mut ptr = bytes.as_ptr(); + let end_ptr = ptr.add(bytes.len()); + // get the len + let len = transmute_len(ptr); + // move ptr ahead by sizeof offset + ptr = ptr.offset(8); + // allocate a map + let map = Coremap::with_capacity(len); + // now enter a loop + for _ in 0..len { + if ptr.add(16) >= end_ptr { + return None; + } + let keylen = transmute_len(ptr); + ptr = ptr.offset(8); + if ptr.add(keylen) >= end_ptr { + return None; + } + // get key + let key = Data::copy_from_slice(slice::from_raw_parts(ptr, keylen)); + // move ptr ahead + ptr = ptr.add(keylen); + if ptr.add(8) >= end_ptr { + // size of list payload is missing + return None; + } + // get list payload len + let list_payload_extent = transmute_len(ptr); + // move ptr ahead + ptr = ptr.offset(8); + let mut list = Vec::with_capacity(list_payload_extent); + for _ in 0..list_payload_extent { + // get element size + if ptr.add(8) >= end_ptr { + // size of list element is missing + return None; + } + let list_element_payload_size = transmute_len(ptr); + // move ptr ahead + ptr = ptr.offset(8); + + // now get element + if ptr.add(list_element_payload_size) >= end_ptr { + // reached end of allocation without getting element + return None; + } + let element = Data::copy_from_slice(slice::from_raw_parts( + ptr, + list_element_payload_size, + )); + list.push(element); + } + + // push it in + map.true_if_insert(key, list); + } + if ptr == end_ptr { + Some(map) + } else { + // someone returned more data + None + } + } + } + #[allow(clippy::needless_return)] // Clippy really misunderstands this pub(super) unsafe fn transmute_len(start_ptr: *const u8) -> usize { little_endian!({