Browse Source

Implement customer [de]serialization for `IntegerInterner`

Added some basic tests that the representation of the interner
is only the `values` sequence, and that it round-trips successfully.
pull/1944/head
Declan Kelly 4 years ago
parent
commit
a3feb8a412
  1. 10
      Cargo.lock
  2. BIN
      cranelift/codegen/src/preopt.serialized
  3. 2
      cranelift/peepmatic/crates/runtime/Cargo.toml
  4. 121
      cranelift/peepmatic/crates/runtime/src/integer_interner.rs

10
Cargo.lock

@ -1338,6 +1338,7 @@ dependencies = [
"peepmatic-automata",
"peepmatic-macro",
"serde",
"serde_test",
"thiserror",
"wast 15.0.0",
]
@ -1881,6 +1882,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_test"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f58190d074af17bd48118303db08afadbd506bc2ba511b4582cebd8f882a9b8d"
dependencies = [
"serde",
]
[[package]]
name = "sha2"
version = "0.8.2"

BIN
cranelift/codegen/src/preopt.serialized

Binary file not shown.

2
cranelift/peepmatic/crates/runtime/Cargo.toml

@ -18,6 +18,8 @@ serde = { version = "1.0.105", features = ["derive"] }
thiserror = "1.0.15"
wast = { version = "15.0.0", optional = true }
[dev-dependencies]
serde_test = "1.0.114"
[features]
# Enable support for a few extra methods that are required by the `peepmatic`

121
cranelift/peepmatic/crates/runtime/src/integer_interner.rs

@ -5,8 +5,12 @@
//! few compared to the full range of `u64`) integers we are matching against
//! here and then reference them by `IntegerId`.
use serde::de::{Deserializer, SeqAccess, Visitor};
use serde::ser::{SerializeSeq, Serializer};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fmt;
use std::marker::PhantomData;
use std::num::{NonZeroU16, NonZeroU32};
/// An identifier for an interned integer.
@ -14,7 +18,7 @@ use std::num::{NonZeroU16, NonZeroU32};
pub struct IntegerId(#[doc(hidden)] pub NonZeroU16);
/// An interner for integer values.
#[derive(Debug, Default, Serialize, Deserialize)]
#[derive(Debug, Default)]
pub struct IntegerInterner {
// Note: we use `BTreeMap`s for deterministic serialization.
map: BTreeMap<u64, IntegerId>,
@ -71,3 +75,118 @@ impl From<IntegerId> for NonZeroU32 {
id.0.into()
}
}
impl Serialize for IntegerInterner {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.values.len()))?;
for p in &self.values {
seq.serialize_element(&p)?;
}
seq.end()
}
}
impl<'de> Deserialize<'de> for IntegerInterner {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(IntegerInternerVisitor {
marker: PhantomData,
})
}
}
struct IntegerInternerVisitor {
marker: PhantomData<fn() -> IntegerInterner>,
}
impl<'de> Visitor<'de> for IntegerInternerVisitor {
type Value = IntegerInterner;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(
formatter,
"a `peepmatic_runtime::integer_interner::IntegerInterner`"
)
}
fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: SeqAccess<'de>,
{
const DEFAULT_CAPACITY: usize = 16;
let capacity = access.size_hint().unwrap_or(DEFAULT_CAPACITY);
let mut interner = IntegerInterner {
map: BTreeMap::new(),
values: Vec::with_capacity(capacity),
};
while let Some(path) = access.next_element::<u64>()? {
interner.intern(path);
}
Ok(interner)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_test::{assert_tokens, Token};
use std::iter::successors;
#[derive(Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct OrderedIntegerInterner(IntegerInterner);
impl PartialEq for OrderedIntegerInterner {
fn eq(&self, other: &OrderedIntegerInterner) -> bool {
self.0.values.iter().eq(other.0.values.iter())
}
}
fn intern_fib(interner: &mut IntegerInterner, skip: usize, take: usize) {
successors(Some((0, 1)), |(a, b): &(u64, u64)| {
a.checked_add(*b).map(|c| (*b, c))
})
.skip(skip)
.take(take)
.for_each(|(i, _)| {
interner.intern(i);
})
}
#[test]
fn test_ser_de_empty_interner() {
let interner = IntegerInterner::new();
assert_tokens(
&OrderedIntegerInterner(interner),
&[Token::Seq { len: Some(0) }, Token::SeqEnd],
);
}
#[test]
fn test_ser_de_fibonacci_interner() {
let mut interner = IntegerInterner::new();
intern_fib(&mut interner, 10, 5);
assert_tokens(
&OrderedIntegerInterner(interner),
&[
Token::Seq { len: Some(5) },
Token::U64(55),
Token::U64(89),
Token::U64(144),
Token::U64(233),
Token::U64(377),
Token::SeqEnd,
],
);
}
}

Loading…
Cancel
Save