use std::hash::Hash;
use rustc_hash::{FxHashMap, FxHashSet};
use super::automaton::Automaton;
pub(super) trait Serialize: Sized {
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>);
fn deserialize(buf: &mut &[u8]) -> Result<Self, String>;
fn deserialize_unwrap(serialization: &[u8]) -> Self {
let mut buf = serialization;
match Self::deserialize(&mut buf) {
Ok(x) => x,
Err(msg) => panic!(
"Deserialization error. Error message:\n=====\n{}\n=====",
msg
),
}
}
}
macro_rules! ensure_buf_len {
($buf:expr, $required:expr, $type:ty) => {
if $buf.len() < $required {
return Err(format!(
"Buffer underflow: expected at least {} bytes for deserializing `{}`, only got {}.\n>> Buffer:\n{:?}",
$required,
stringify!($type),
$buf.len(),
$buf,
));
}
};
}
impl Serialize for u8 {
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
buf.push(*self)
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
ensure_buf_len!(buf, 1, Self);
let res = buf[0];
*buf = &buf[1..];
Ok(res)
}
}
impl Serialize for u64 {
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
buf.extend(&self.to_le_bytes())
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
const U64_BYTES: usize = u64::BITS as usize / 8;
ensure_buf_len!(buf, U64_BYTES, Self);
let res = Self::from_le_bytes(buf[..U64_BYTES].try_into().unwrap());
*buf = &buf[U64_BYTES..];
Ok(res)
}
}
impl Serialize for usize {
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
(*self as u64).serialize(buf)
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
let val = u64::deserialize(buf)?;
if val > (usize::MAX as u64) {
Err(format!(
"Cannot deserialize value {} into usize on this platform",
val
))
} else {
Ok(val as usize)
}
}
}
impl Serialize for bool {
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
if *self { 1u8 } else { 0u8 }.serialize(buf)
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
Ok(u8::deserialize(buf)? == 1)
}
}
impl<T> Serialize for Option<T>
where
T: Serialize,
{
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
match self {
None => false.serialize(buf),
Some(x) => {
true.serialize(buf);
x.serialize(buf);
}
}
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
if !bool::deserialize(buf)? {
Ok(None)
} else {
Ok(Some(T::deserialize(buf)?))
}
}
}
impl<T, U> Serialize for (T, U)
where
T: Serialize,
U: Serialize,
{
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
self.0.serialize(buf);
self.1.serialize(buf);
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
let x = T::deserialize(buf)?;
let y = U::deserialize(buf)?;
Ok((x, y))
}
}
impl<T, U, V> Serialize for (T, U, V)
where
T: Serialize,
U: Serialize,
V: Serialize,
{
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
self.0.serialize(buf);
self.1.serialize(buf);
self.2.serialize(buf);
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
let x = T::deserialize(buf)?;
let y = U::deserialize(buf)?;
let z = V::deserialize(buf)?;
Ok((x, y, z))
}
}
impl<T> Serialize for Vec<T>
where
T: Serialize,
{
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
self.len().serialize(buf);
for x in self {
x.serialize(buf)
}
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
let len = usize::deserialize(buf)?;
let mut res = Vec::with_capacity(len);
for _ in 0..len {
res.push(T::deserialize(buf)?);
}
Ok(res)
}
}
impl<T> Serialize for FxHashSet<T>
where
T: Serialize + Copy + Hash + Ord,
{
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
let mut v = Vec::from_iter(self.iter().copied());
v.sort();
v.serialize(buf)
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
let v = Vec::<T>::deserialize(buf)?;
Ok(FxHashSet::from_iter(v))
}
}
impl<K, T> Serialize for FxHashMap<K, T>
where
K: Serialize + Copy + Hash + Ord,
T: Serialize + Clone,
{
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
let mut v = Vec::from_iter(self.iter().map(|(k, v)| (*k, v.clone())));
v.sort_by_key(|e| e.0);
v.serialize(buf)
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
let v = Vec::<(K, T)>::deserialize(buf)?;
Ok(FxHashMap::from_iter(v))
}
}
macro_rules! impl_serialize_for_struct {
($type:ident { $($field:ident),* }) => {
impl Serialize for $type {
#[cfg(test)]
fn serialize(&self, buf: &mut Vec<u8>) {
$( self.$field.serialize(buf); )*
}
fn deserialize(buf: &mut &[u8]) -> Result<Self, String> {
$( let $field = Serialize::deserialize(buf)?; )*
Ok(Self { $($field),* })
}
}
};
}
impl_serialize_for_struct!(Automaton {
nb_states,
initial_state,
final_states,
transitions
});
#[cfg(test)]
mod tests {
use std::fmt::Debug;
use rustc_hash::{FxHashMap, FxHashSet};
use super::Serialize;
fn serialization_one_test<T>(x: T, type_name: &str)
where
T: Serialize + Debug + Eq,
{
println!(">> Testing the {} serialization: {:?}", type_name, x);
let mut buf = Vec::new();
x.serialize(&mut buf);
let mut slice: &[u8] = &buf;
let y = T::deserialize(&mut slice);
let y = match y {
Err(s) => panic!(
"deserialization failed!\nBuffer: {:?}\nError message: {}",
buf, s
),
Ok(y) => y,
};
assert!(x == y, "incorrect serialization!\nBuffer: {:?}", buf);
println!("serialization succeeded!\nBuffer: {:?}", buf);
}
#[test]
fn serialization_test() {
serialization_one_test(2134098563175846_usize, "usize");
serialization_one_test(213409856315_u64, "u64");
for i in 0..256 {
serialization_one_test(i as u8, "u8");
}
serialization_one_test(true, "bool");
serialization_one_test(false, "bool");
let test_vector: Vec<usize> = vec![0, 1, 2, 3, 4, 5, 6, 7];
let test_vector_pairs: Vec<(usize, u8)> =
vec![(82365, 0), (82365, 2), (825, 4), (82365, 6), (82365, 7)];
serialization_one_test(test_vector.clone(), "Vec<usize>");
serialization_one_test(Some(test_vector.clone()), "Option<Vec<usize>>");
serialization_one_test(None::<u64>, "Option<Vec<usize>>");
serialization_one_test(None::<bool>, "Option<Vec<usize>>");
serialization_one_test(
None::<(
Vec<(bool, usize)>,
FxHashMap<usize, u64>,
FxHashSet<(u64, usize, bool)>,
)>,
"Option<Vec<usize>>",
);
serialization_one_test(test_vector_pairs.clone(), "Vec<(usize,u8)>");
serialization_one_test(
(test_vector_pairs.clone(), 84065_u64, true),
"(Vec<(usize,u8)>, u64, bool)",
);
serialization_one_test(
FxHashSet::from_iter(test_vector.clone()),
"FxHashSet<usize>",
);
serialization_one_test(
FxHashMap::from_iter(test_vector_pairs.clone()),
"FxHashMap<usize,u8>",
);
}
#[test]
fn test_serialization_regex_instructions() {
}
}