1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
use crate::{Bitmap64, Portable};
use std::ffi::c_char;
use std::num::NonZeroUsize;
/// Trait for different formats of bitmap64 serialization
pub trait Serializer {
/// Serialize a bitmap into bytes, using the provided vec buffer to store the serialized data
///
/// Note that some serializers ([Frozen][crate::Frozen]) may require that the
/// bitmap is aligned specially, this method will ensure that the returned slice of bytes is
/// aligned correctly, by adding additional padding before the serialized data if required.
///
/// The contents of the provided vec buffer will not be overwritten: only new data will be
/// appended to the end of the buffer. If the buffer has enough capacity, and the current
/// end of the buffer is correctly aligned, then no additional allocations will be performed.
fn serialize_into<'a>(bitmap: &Bitmap64, dst: &'a mut Vec<u8>) -> &'a [u8];
/// Get the number of bytes required to serialize this bitmap
///
/// This does not include any additional padding which may be required to align the bitmap
fn get_serialized_size_in_bytes(bitmap: &Bitmap64) -> usize;
}
/// Trait for different formats of bitmap deserialization
pub trait Deserializer {
/// Try to deserialize a bitmap from the beginning of the provided buffer
///
/// The [`Bitmap64::try_deserialize`] method should usually be used instead of this method
/// directly.
///
/// If the buffer starts with the serialized representation of a bitmap, then
/// this method will return a new bitmap containing the deserialized data.
///
/// If the buffer does not start with a serialized bitmap (or contains an invalidly
/// truncated bitmap), then this method will return `None`.
///
/// To determine how many bytes were consumed from the buffer, use the
/// [`Serializer::get_serialized_size_in_bytes`] method on the returned bitmap.
fn try_deserialize(buffer: &[u8]) -> Option<Bitmap64>;
/// Deserialize a bitmap from the beginning of the provided buffer
///
/// # Safety
///
/// Unlike its safe counterpart, [`Self::try_deserialize`], this function assumes the data is valid,
/// passing data which does not contain/start with a bitmap serialized with this format will
/// result in undefined behavior.
unsafe fn try_deserialize_unchecked(buffer: &[u8]) -> Bitmap64;
/// Find the end of a serialized bitmap in portable format
///
/// Returns the number of bytes in the buffer which are part of the serialized bitmap, or `None` if
/// the buffer does not start with a valid serialized bitmap.
fn find_end(buffer: &[u8]) -> Option<NonZeroUsize>;
}
impl Serializer for Portable {
/// Serialize a bitmap to a slice of bytes in portable format.
///
/// See [`Bitmap64::serialize_into`] for more details.
#[doc(alias = "roaring64_bitmap_portable_serialize")]
fn serialize_into<'a>(bitmap: &Bitmap64, dst: &'a mut Vec<u8>) -> &'a [u8] {
let len = Self::get_serialized_size_in_bytes(bitmap);
dst.reserve(len);
let offset = dst.len();
let total_len = offset.checked_add(len).unwrap();
unsafe {
ffi::roaring64_bitmap_portable_serialize(
bitmap.raw.as_ptr(),
dst.spare_capacity_mut().as_mut_ptr().cast::<c_char>(),
);
dst.set_len(total_len);
}
&dst[offset..]
}
/// Computes the serialized size in bytes of the Bitmap in portable format.
/// See [`Bitmap64::get_serialized_size_in_bytes`] for examples.
#[doc(alias = "roaring64_bitmap_portable_size_in_bytes")]
fn get_serialized_size_in_bytes(bitmap: &Bitmap64) -> usize {
unsafe { ffi::roaring64_bitmap_portable_size_in_bytes(bitmap.raw.as_ptr()) }
}
}
impl Deserializer for Portable {
#[doc(alias = "roaring64_bitmap_portable_deserialize_safe")]
fn try_deserialize(buffer: &[u8]) -> Option<Bitmap64> {
let raw = unsafe {
ffi::roaring64_bitmap_portable_deserialize_safe(buffer.as_ptr().cast(), buffer.len())
};
if raw.is_null() {
return None;
}
unsafe {
let bitmap = Bitmap64::take_heap(raw);
if bitmap.internal_validate().is_ok() {
Some(bitmap)
} else {
None
}
}
}
unsafe fn try_deserialize_unchecked(buffer: &[u8]) -> Bitmap64 {
Self::try_deserialize(buffer).unwrap_unchecked()
}
fn find_end(buffer: &[u8]) -> Option<NonZeroUsize> {
let end = unsafe {
ffi::roaring64_bitmap_portable_deserialize_size(
buffer.as_ptr().cast::<c_char>(),
buffer.len(),
)
};
NonZeroUsize::new(end)
}
}