croaring/bitmap64/serialization.rs
1use crate::{Bitmap64, Frozen, Portable};
2use core::ffi::c_char;
3use core::num::NonZeroUsize;
4
5/// Trait for different formats of bitmap64 serialization
6pub trait Serializer: crate::sealed::Sealed {
7 /// The required alignment for the serialized data
8 #[doc(hidden)]
9 const REQUIRED_ALIGNMENT: usize = 1;
10
11 /// Serialize a bitmap into bytes, using the provided vec buffer to store the serialized data
12 ///
13 /// Note that some serializers ([Frozen][crate::Frozen]) may require that the
14 /// bitmap is aligned specially, this method will ensure that the returned slice of bytes is
15 /// aligned correctly, by adding additional padding before the serialized data if required.
16 ///
17 /// The contents of the provided vec buffer will not be overwritten: only new data will be
18 /// appended to the end of the buffer. If the buffer has enough capacity, and the current
19 /// end of the buffer is correctly aligned, then no additional allocations will be performed.
20 #[doc(hidden)]
21 #[cfg(feature = "alloc")]
22 fn serialize_into_vec<'a>(bitmap: &Bitmap64, dst: &'a mut alloc::vec::Vec<u8>) -> &'a mut [u8] {
23 let len = Self::get_serialized_size_in_bytes(bitmap);
24 let spare_capacity =
25 crate::serialization::get_aligned_spare_capacity(dst, Self::REQUIRED_ALIGNMENT, len);
26 let data_start;
27 unsafe {
28 Self::raw_serialize(bitmap, spare_capacity.as_mut_ptr().cast::<c_char>());
29 data_start = dst.len();
30 let total_len = data_start.checked_add(len).unwrap();
31 dst.set_len(total_len);
32 }
33
34 &mut dst[data_start..]
35 }
36
37 #[doc(hidden)]
38 fn try_serialize_into_aligned<'a>(
39 bitmap: &Bitmap64,
40 dst: &'a mut [u8],
41 ) -> Option<&'a mut [u8]> {
42 let offset = dst.as_ptr().align_offset(Self::REQUIRED_ALIGNMENT);
43 let offset_dst = dst.get_mut(offset..)?;
44 let len = Self::try_serialize_into(bitmap, offset_dst)?;
45 Some(&mut dst[offset..offset + len])
46 }
47
48 /// Serialize a bitmap into bytes, using the provided buffer to store the serialized data
49 ///
50 /// This method does not require the buffer to be aligned, and will return `None` if the buffer
51 /// is not large enough to store the serialized data. Some serializers may have other
52 /// conditions where this method will return `None`, for example the [`crate::Frozen`] format
53 /// requires the bitmap to be shrunk with [`Bitmap64::shrink_to_fit`] before it can be
54 /// serialized.
55 ///
56 /// This is a niche method, and is not recommended for general use. The
57 /// [`Bitmap64::try_serialize_into`]/[`Bitmap64::serialize_into_vec`] methods should usually be used
58 /// instead of this method.
59 fn try_serialize_into(bitmap: &Bitmap64, dst: &mut [u8]) -> Option<usize> {
60 let required_len = Self::get_serialized_size_in_bytes(bitmap);
61 if dst.len() < required_len || required_len == 0 {
62 return None;
63 }
64 unsafe {
65 Self::raw_serialize(bitmap, dst.as_mut_ptr().cast::<c_char>());
66 }
67 Some(required_len)
68 }
69
70 /// Get the number of bytes required to serialize this bitmap
71 ///
72 /// This does not include any additional padding which may be required to align the bitmap
73 #[doc(hidden)]
74 fn get_serialized_size_in_bytes(bitmap: &Bitmap64) -> usize;
75
76 #[doc(hidden)]
77 unsafe fn raw_serialize(bitmap: &Bitmap64, dst: *mut c_char);
78}
79
80/// Trait for different formats of bitmap deserialization
81pub trait Deserializer: crate::sealed::Sealed {
82 /// Try to deserialize a bitmap from the beginning of the provided buffer
83 ///
84 /// The [`Bitmap64::try_deserialize`] method should usually be used instead of this method
85 /// directly.
86 ///
87 /// If the buffer starts with the serialized representation of a bitmap, then
88 /// this method will return a new bitmap containing the deserialized data.
89 ///
90 /// If the buffer does not start with a serialized bitmap (or contains an invalidly
91 /// truncated bitmap), then this method will return `None`.
92 ///
93 /// To determine how many bytes were consumed from the buffer, use the
94 /// [`Serializer::get_serialized_size_in_bytes`] method on the returned bitmap.
95 fn try_deserialize(buffer: &[u8]) -> Option<Bitmap64>;
96
97 /// Deserialize a bitmap from the beginning of the provided buffer
98 ///
99 /// # Safety
100 ///
101 /// Unlike its safe counterpart, [`Self::try_deserialize`], this function assumes the data is valid,
102 /// passing data which does not contain/start with a bitmap serialized with this format will
103 /// result in undefined behavior.
104 unsafe fn try_deserialize_unchecked(buffer: &[u8]) -> Bitmap64;
105
106 /// Find the end of a serialized bitmap in portable format
107 ///
108 /// Returns the number of bytes in the buffer which are part of the serialized bitmap, or `None` if
109 /// the buffer does not start with a valid serialized bitmap.
110 fn find_end(buffer: &[u8]) -> Option<NonZeroUsize>;
111}
112
113pub trait ViewDeserializer: crate::sealed::Sealed {
114 /// Create a bitmap64 view using the passed data
115 ///
116 /// # Safety
117 /// * `data` must be the result of serializing a roaring bitmap in this format.
118 /// * Its beginning must be aligned properly for this format.
119 /// * data.len() must be equal exactly to the size of the serialized bitmap.
120 ///
121 /// See [`Bitmap64View::deserialize`] for examples.
122 #[doc(hidden)]
123 unsafe fn deserialize_view(data: &[u8]) -> *mut ffi::roaring64_bitmap_t;
124}
125
126impl Serializer for Portable {
127 /// Computes the serialized size in bytes of the Bitmap in portable format.
128 /// See [`Bitmap64::get_serialized_size_in_bytes`] for examples.
129 #[doc(alias = "roaring64_bitmap_portable_size_in_bytes")]
130 fn get_serialized_size_in_bytes(bitmap: &Bitmap64) -> usize {
131 unsafe { ffi::roaring64_bitmap_portable_size_in_bytes(bitmap.raw.as_ptr()) }
132 }
133
134 unsafe fn raw_serialize(bitmap: &Bitmap64, dst: *mut c_char) {
135 unsafe {
136 ffi::roaring64_bitmap_portable_serialize(bitmap.raw.as_ptr(), dst);
137 }
138 }
139}
140
141impl Deserializer for Portable {
142 #[doc(alias = "roaring64_bitmap_portable_deserialize_safe")]
143 fn try_deserialize(buffer: &[u8]) -> Option<Bitmap64> {
144 let raw = unsafe {
145 ffi::roaring64_bitmap_portable_deserialize_safe(buffer.as_ptr().cast(), buffer.len())
146 };
147 if raw.is_null() {
148 return None;
149 }
150
151 unsafe {
152 let bitmap = Bitmap64::take_heap(raw);
153 if bitmap.internal_validate().is_ok() {
154 Some(bitmap)
155 } else {
156 None
157 }
158 }
159 }
160
161 unsafe fn try_deserialize_unchecked(buffer: &[u8]) -> Bitmap64 {
162 Self::try_deserialize(buffer).unwrap_unchecked()
163 }
164
165 fn find_end(buffer: &[u8]) -> Option<NonZeroUsize> {
166 let end = unsafe {
167 ffi::roaring64_bitmap_portable_deserialize_size(
168 buffer.as_ptr().cast::<c_char>(),
169 buffer.len(),
170 )
171 };
172 NonZeroUsize::new(end)
173 }
174}
175
176impl Serializer for Frozen {
177 // Unlike 32 bit bitmaps, 64 bit bitmaps require 64 byte alignment
178 const REQUIRED_ALIGNMENT: usize = 64;
179
180 fn get_serialized_size_in_bytes(bitmap: &Bitmap64) -> usize {
181 unsafe { ffi::roaring64_bitmap_frozen_size_in_bytes(bitmap.raw.as_ptr()) }
182 }
183
184 unsafe fn raw_serialize(bitmap: &Bitmap64, dst: *mut c_char) {
185 unsafe {
186 ffi::roaring64_bitmap_frozen_serialize(bitmap.raw.as_ptr(), dst);
187 }
188 }
189}
190
191impl ViewDeserializer for Frozen {
192 unsafe fn deserialize_view(data: &[u8]) -> *mut ffi::roaring64_bitmap_t {
193 unsafe { ffi::roaring64_bitmap_frozen_view(data.as_ptr().cast(), data.len()) }
194 }
195}