use crate::actor::{Envelope, Id};
use crate::util::{HashableHashMap, HashableHashSet};
use crate::RewritePlan;
use std::collections::{BTreeMap, BTreeSet, VecDeque};
use std::hash::Hash;
use std::sync::Arc;
pub trait Rewrite<R> {
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self;
}
macro_rules! impl_noop_rewrite {
( $( $t:ty ),* ) => {
$(
impl<R> crate::Rewrite<R> for $t {
#[inline(always)]
fn rewrite<S>(&self, _: &RewritePlan<R,S>) -> Self { self.clone() }
}
)*
}
}
impl_noop_rewrite![
(),
bool,
char,
f32,
f64,
i8,
i16,
i32,
i64,
isize,
&'static str,
u8,
u16,
u32,
u64,
usize,
String
];
impl<R, T0, T1> Rewrite<R> for (T0, T1)
where
T0: Rewrite<R>,
T1: Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
(self.0.rewrite(plan), self.1.rewrite(plan))
}
}
impl<R, T> Rewrite<R> for Arc<T>
where
T: Rewrite<R>,
{
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
Arc::new((**self).rewrite(plan))
}
}
impl<R, K, V> Rewrite<R> for BTreeMap<K, V>
where
K: Ord + Rewrite<R>,
V: Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.iter()
.map(|(k, v)| (k.rewrite(plan), v.rewrite(plan)))
.collect()
}
}
impl<R, V> Rewrite<R> for BTreeSet<V>
where
V: Ord + Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.iter().map(|x| x.rewrite(plan)).collect()
}
}
impl<R, V> Rewrite<R> for HashableHashSet<V>
where
V: Eq + Hash + Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.iter().map(|x| x.rewrite(plan)).collect()
}
}
impl<R, K, V> Rewrite<R> for HashableHashMap<K, V>
where
V: Eq + Hash + Rewrite<R>,
K: Eq + Hash + Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.iter()
.map(|(k, v)| (k.rewrite(plan), v.rewrite(plan)))
.collect()
}
}
impl<R, T> Rewrite<R> for Option<T>
where
T: Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.as_ref().map(|v| v.rewrite(plan))
}
}
impl<R, V> Rewrite<R> for Vec<V>
where
V: Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.iter().map(|x| x.rewrite(plan)).collect()
}
}
impl<R, V> Rewrite<R> for VecDeque<V>
where
V: Rewrite<R>,
{
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<R, S>) -> Self {
self.iter().map(|x| x.rewrite(plan)).collect()
}
}
impl Rewrite<Id> for Id {
#[inline(always)]
fn rewrite<S>(&self, plan: &RewritePlan<Id, S>) -> Self {
plan.rewrite(self)
}
}
impl<Msg> Rewrite<Id> for Envelope<Msg>
where
Msg: Rewrite<Id>,
{
fn rewrite<S>(&self, plan: &RewritePlan<Id, S>) -> Self {
Envelope {
src: self.src.rewrite(plan),
dst: self.dst.rewrite(plan),
msg: self.msg.rewrite(plan),
}
}
}
#[cfg(test)]
mod test {
use crate::actor::{Envelope, Id, Network};
use crate::{Rewrite, RewritePlan};
#[test]
fn can_rewrite_id_vec() {
let original = Id::vec_from(vec![1, 2, 2]);
assert_eq!(
original.rewrite(&RewritePlan::<Id, _>::from_values_to_sort(&vec![2, 0, 1])),
Id::vec_from(vec![0, 1, 1])
);
assert_eq!(
original.rewrite(&RewritePlan::<Id, _>::from_values_to_sort(&vec![0, 2, 1])),
Id::vec_from(vec![2, 1, 1])
);
}
#[test]
#[rustfmt::skip]
fn can_rewrite_network() {
let original: Network<_> = Network::new_unordered_duplicating([
Envelope { src: 0.into(), dst: 1.into(), msg: "Write(X)" },
Envelope { src: 0.into(), dst: 2.into(), msg: "Write(X)" },
Envelope { src: 1.into(), dst: 0.into(), msg: "Ack(X)" },
Envelope { src: 2.into(), dst: 0.into(), msg: "Ack(X)" },
Envelope { src: 2.into(), dst: 0.into(), msg: "Write(Y)" },
Envelope { src: 2.into(), dst: 1.into(), msg: "Write(Y)" },
Envelope { src: 1.into(), dst: 2.into(), msg: "Ack(Y)" },
]);
assert_eq!(
original.rewrite(&RewritePlan::from_values_to_sort(&vec![2, 0, 1])),
Network::new_unordered_duplicating([
Envelope { src: 2.into(), dst: 0.into(), msg: "Write(X)" },
Envelope { src: 2.into(), dst: 1.into(), msg: "Write(X)" },
Envelope { src: 0.into(), dst: 2.into(), msg: "Ack(X)" },
Envelope { src: 1.into(), dst: 2.into(), msg: "Ack(X)" },
Envelope { src: 1.into(), dst: 2.into(), msg: "Write(Y)" },
Envelope { src: 1.into(), dst: 0.into(), msg: "Write(Y)" },
Envelope { src: 0.into(), dst: 1.into(), msg: "Ack(Y)" },
]));
assert_eq!(
original.rewrite(&RewritePlan::from_values_to_sort(&vec![0, 2, 1])),
Network::new_unordered_duplicating([
Envelope { src: 0.into(), dst: 2.into(), msg: "Write(X)" },
Envelope { src: 0.into(), dst: 1.into(), msg: "Write(X)" },
Envelope { src: 2.into(), dst: 0.into(), msg: "Ack(X)" },
Envelope { src: 1.into(), dst: 0.into(), msg: "Ack(X)" },
Envelope { src: 1.into(), dst: 0.into(), msg: "Write(Y)" },
Envelope { src: 1.into(), dst: 2.into(), msg: "Write(Y)" },
Envelope { src: 2.into(), dst: 1.into(), msg: "Ack(Y)" },
]));
}
}