Implement serde and equality traits for SecondaryMap
This commit is contained in:
@@ -33,7 +33,7 @@ pub type CodeOffset = u32;
|
|||||||
pub type Addend = i64;
|
pub type Addend = i64;
|
||||||
|
|
||||||
/// Relocation kinds for every ISA
|
/// Relocation kinds for every ISA
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum Reloc {
|
pub enum Reloc {
|
||||||
/// absolute 4-byte
|
/// absolute 4-byte
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ impl fmt::Display for StackSlotKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Contents of a stack slot.
|
/// Contents of a stack slot.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct StackSlotData {
|
pub struct StackSlotData {
|
||||||
/// The kind of stack slot.
|
/// The kind of stack slot.
|
||||||
@@ -154,7 +154,7 @@ impl fmt::Display for StackSlotData {
|
|||||||
/// Stack frame manager.
|
/// Stack frame manager.
|
||||||
///
|
///
|
||||||
/// Keep track of all the stack slots used by a function.
|
/// 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))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct StackSlots {
|
pub struct StackSlots {
|
||||||
/// All allocated stack slots.
|
/// All allocated stack slots.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use std::vec::Vec;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Value location range.
|
/// Value location range.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ValueLocRange {
|
pub struct ValueLocRange {
|
||||||
/// The ValueLoc containing a ValueLabel during this range.
|
/// The ValueLoc containing a ValueLabel during this range.
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ use crate::EntityRef;
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::ops::{Index, IndexMut};
|
use core::ops::{Index, IndexMut};
|
||||||
use core::slice;
|
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;
|
use std::vec::Vec;
|
||||||
|
|
||||||
/// A mapping `K -> V` for densely indexed entity references.
|
/// 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.
|
/// Get the element at `k` if it exists.
|
||||||
pub fn get(&self, k: K) -> Option<&V> {
|
pub fn get(&self, k: K) -> Option<&V> {
|
||||||
self.elems.get(k.index())
|
self.elems.get(k.index())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the default value.
|
|
||||||
pub fn get_default(&self) -> &V {
|
|
||||||
&self.default
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Is this map completely empty?
|
/// Is this map completely empty?
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.elems.is_empty()
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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
|
/// 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
|
/// plain slice would make it easier to use incorrectly. To make a slice of a `PrimaryMap`, use
|
||||||
/// `into_boxed_slice`.
|
/// `into_boxed_slice`.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct PrimaryMap<K, V>
|
pub struct PrimaryMap<K, V>
|
||||||
where
|
where
|
||||||
|
|||||||
Reference in New Issue
Block a user