Skip to content

Commit

Permalink
Replace inner concrete model enum with trait object and dynamic dispatch
Browse files Browse the repository at this point in the history
  • Loading branch information
kirushyk committed Mar 30, 2021
1 parent 4b28b04 commit 26a9611
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 103 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ crate-type = ["cdylib", "rlib"]
default = ["console_error_panic_hook"]

[dependencies]
enum_dispatch = "0.3"
# enum_dispatch = "0.3"
getrandom = { version = "0.2", features = ["js"] }
js-sys = "0.3"
num-traits = "0.2"
Expand Down
2 changes: 1 addition & 1 deletion src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use self::exclusive_gateway::ExclusiveGateway;
pub use self::gate::Gate;
pub use self::generator::Generator;
pub use self::load_balancer::LoadBalancer;
pub use self::model::{AsModel, Model, ModelType};
pub use self::model::{AsModel, Model/*, ModelType*/};
pub use self::parallel_gateway::ParallelGateway;
pub use self::processor::Processor;
pub use self::stochastic_gate::StochasticGate;
Expand Down
91 changes: 58 additions & 33 deletions src/models/model.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
use enum_dispatch::enum_dispatch;
use serde::{Deserialize, Serialize};
// use enum_dispatch::enum_dispatch;
use serde::{Serialize, Serializer};
use serde::de::{self, Deserialize, Deserializer};
use std::rc::Rc;
use std::cell::RefCell;

use super::ExclusiveGateway;
use super::Gate;
use super::Generator;
use super::LoadBalancer;
// use super::ExclusiveGateway;
// use super::Gate;
// use super::Generator;
// use super::LoadBalancer;
use super::ModelMessage;
use super::ParallelGateway;
use super::Processor;
use super::StochasticGate;
use super::Storage;
// use super::ParallelGateway;
// use super::Processor;
// use super::StochasticGate;
// use super::Storage;
use crate::input_modeling::UniformRNG;
use crate::utils::error::SimulationError;

/// `Model` wraps `ModelType` and provides common ID functionality (a struct
/// field and associated accessor method). The simulator requires all models
/// to have an ID.
#[derive(Debug, Clone, Serialize, Deserialize)]
//#[derive(/*Debug, Clone, Serialize, Deserialize*/)]
pub struct Model {
id: String,
#[serde(flatten)]
inner: ModelType,
inner: Rc<RefCell<dyn AsModel>>,
}

impl Model {
pub fn new(id: String, inner: ModelType) -> Self {
pub fn new(id: String, inner: Rc<RefCell<dyn AsModel>>) -> Self {
Self { id, inner }
}

Expand All @@ -33,57 +35,80 @@ impl Model {
}
}

impl Clone for Model {
fn clone(&self) -> Self {
// Fix self.inner cloning
Model {
id: self.id.clone(),
inner: self.inner.clone()
}
}
}

impl Serialize for Model {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&self.id)
}
}

impl<'de> Deserialize<'de> for Model {
fn deserialize<D: Deserializer<'de>>(_: D) -> Result<Self, D::Error> {
Err(de::Error::missing_field("type"))
// deserializer.deserialize_struct(name: &'static str, fields: &'static [&'static str], visitor: V)
}
}

impl AsModel for Model {
fn status(&self) -> String {
self.inner.status()
self.inner.borrow().status()
}

fn events_ext(
&mut self,
uniform_rng: &mut UniformRNG,
incoming_message: ModelMessage,
) -> Result<Vec<ModelMessage>, SimulationError> {
self.inner.events_ext(uniform_rng, incoming_message)
self.inner.borrow_mut().events_ext(uniform_rng, incoming_message)
}

fn events_int(
&mut self,
uniform_rng: &mut UniformRNG,
) -> Result<Vec<ModelMessage>, SimulationError> {
self.inner.events_int(uniform_rng)
self.inner.borrow_mut().events_int(uniform_rng)
}

fn time_advance(&mut self, time_delta: f64) {
self.inner.time_advance(time_delta)
self.inner.borrow_mut().time_advance(time_delta)
}

fn until_next_event(&self) -> f64 {
self.inner.until_next_event()
self.inner.borrow_mut().until_next_event()
}
}

/// `ModelType` is an enum encompassing all the available model types. Each
/// variant holds a concrete type that implements AsModel.
#[enum_dispatch(AsModel)]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(tag = "type")]
pub enum ModelType {
ExclusiveGateway,
Gate,
Generator,
LoadBalancer,
ParallelGateway,
Processor,
StochasticGate,
Storage,
}
// #[enum_dispatch(AsModel)]
// #[derive(Serialize, Deserialize, Clone, Debug)]
// #[serde(tag = "type")]
// pub enum ModelType {
// ExclusiveGateway,
// Gate,
// Generator,
// LoadBalancer,
// ParallelGateway,
// Processor,
// StochasticGate,
// Storage,
// }

/// The `AsModel` trait defines everything required for a model to operate
/// within the discrete event simulation. The simulator formalism (Discrete
/// Event System Specification) requires `events_ext`, `events_int`,
/// `time_advance`, and `until_next_event`. The additional `status` is for
/// facilitation of simulation reasoning, reporting, and debugging.
#[enum_dispatch]
// #[enum_dispatch]
pub trait AsModel {
fn status(&self) -> String;
fn events_ext(
Expand Down
Loading

0 comments on commit 26a9611

Please sign in to comment.