Implement serde and equality traits for SecondaryMap
This commit is contained in:
@@ -33,7 +33,7 @@ pub type CodeOffset = u32;
|
||||
pub type Addend = i64;
|
||||
|
||||
/// Relocation kinds for every ISA
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub enum Reloc {
|
||||
/// absolute 4-byte
|
||||
|
||||
@@ -101,7 +101,7 @@ impl fmt::Display for StackSlotKind {
|
||||
}
|
||||
|
||||
/// Contents of a stack slot.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct StackSlotData {
|
||||
/// The kind of stack slot.
|
||||
@@ -154,7 +154,7 @@ impl fmt::Display for StackSlotData {
|
||||
/// Stack frame manager.
|
||||
///
|
||||
/// Keep track of all the stack slots used by a function.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct StackSlots {
|
||||
/// All allocated stack slots.
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::vec::Vec;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Value location range.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct ValueLocRange {
|
||||
/// The ValueLoc containing a ValueLabel during this range.
|
||||
|
||||
@@ -6,6 +6,13 @@ use crate::EntityRef;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::slice;
|
||||
#[cfg(feature = "enable-serde")]
|
||||
use serde::{
|
||||
de::{Deserializer, SeqAccess, Visitor},
|
||||
ser::{SerializeSeq, Serializer},
|
||||
Deserialize, Serialize,
|
||||
};
|
||||
use std::cmp::min;
|
||||
use std::vec::Vec;
|
||||
|
||||
/// A mapping `K -> V` for densely indexed entity references.
|
||||
@@ -56,23 +63,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the underlying vector.
|
||||
///
|
||||
/// The number is not necessarily the same as the length of the corresponding PrimaryMap.
|
||||
pub fn len(&self) -> usize {
|
||||
self.elems.len()
|
||||
}
|
||||
|
||||
/// Get the element at `k` if it exists.
|
||||
pub fn get(&self, k: K) -> Option<&V> {
|
||||
self.elems.get(k.index())
|
||||
}
|
||||
|
||||
/// Get the default value.
|
||||
pub fn get_default(&self) -> &V {
|
||||
&self.default
|
||||
}
|
||||
|
||||
/// Is this map completely empty?
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.elems.is_empty()
|
||||
@@ -148,6 +143,106 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> PartialEq for SecondaryMap<K, V>
|
||||
where
|
||||
K: EntityRef,
|
||||
V: Clone + PartialEq,
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let min_size = min(self.elems.len(), other.elems.len());
|
||||
self.default == other.default
|
||||
&& self.elems[..min_size] == other.elems[..min_size]
|
||||
&& self.elems[min_size..].iter().all(|e| *e == self.default)
|
||||
&& other.elems[min_size..].iter().all(|e| *e == other.default)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Eq for SecondaryMap<K, V>
|
||||
where
|
||||
K: EntityRef,
|
||||
V: Clone + PartialEq + Eq,
|
||||
{
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-serde")]
|
||||
impl<K, V> Serialize for SecondaryMap<K, V>
|
||||
where
|
||||
K: EntityRef,
|
||||
V: Clone + PartialEq + Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// TODO: bincode encodes option as "byte for Some/None" and then optionally the content
|
||||
// TODO: we can actually optimize it by encoding manually bitmask, then elements
|
||||
let mut elems_cnt = self.elems.len();
|
||||
while elems_cnt > 0 && self.elems[elems_cnt - 1] == self.default {
|
||||
elems_cnt -= 1;
|
||||
}
|
||||
let mut seq = serializer.serialize_seq(Some(1 + elems_cnt))?;
|
||||
seq.serialize_element(&Some(self.default.clone()))?;
|
||||
for e in self.elems.iter().take(elems_cnt) {
|
||||
let some_e = Some(e);
|
||||
seq.serialize_element(if *e == self.default { &None } else { &some_e })?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-serde")]
|
||||
impl<'de, K, V> Deserialize<'de> for SecondaryMap<K, V>
|
||||
where
|
||||
K: EntityRef,
|
||||
V: Clone + Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
use std::fmt;
|
||||
struct SecondaryMapVisitor<K, V> {
|
||||
unused: PhantomData<fn(K) -> V>,
|
||||
}
|
||||
|
||||
impl<'de, K, V> Visitor<'de> for SecondaryMapVisitor<K, V>
|
||||
where
|
||||
K: EntityRef,
|
||||
V: Clone + Deserialize<'de>,
|
||||
{
|
||||
type Value = SecondaryMap<K, V>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("struct SecondaryMap")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
match seq.next_element()? {
|
||||
Some(Some(default_val)) => {
|
||||
let default_val: V = default_val; // compiler can't infer the type
|
||||
let mut m = SecondaryMap::with_default(default_val.clone());
|
||||
let mut idx = 0;
|
||||
while let Some(val) = seq.next_element()? {
|
||||
let val: Option<_> = val; // compiler can't infer the type
|
||||
m[K::new(idx)] = val.unwrap_or_else(|| default_val.clone());
|
||||
idx += 1;
|
||||
}
|
||||
Ok(m)
|
||||
}
|
||||
_ => Err(serde::de::Error::custom("Default value required")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(SecondaryMapVisitor {
|
||||
unused: PhantomData {},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -27,7 +27,7 @@ use std::vec::Vec;
|
||||
/// that it only allows indexing with the distinct `EntityRef` key type, so converting to a
|
||||
/// plain slice would make it easier to use incorrectly. To make a slice of a `PrimaryMap`, use
|
||||
/// `into_boxed_slice`.
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct PrimaryMap<K, V>
|
||||
where
|
||||
|
||||
Reference in New Issue
Block a user