Skip to content

Commit

Permalink
refactor: outsource dynamic type checking
Browse files Browse the repository at this point in the history
  • Loading branch information
FWuermse committed Aug 17, 2023
1 parent f4184ab commit 0de9a7b
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 87 deletions.
87 changes: 3 additions & 84 deletions src/flow/app_state.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use std::{
any::Any,
collections::HashMap,
ops::Add,
sync::{mpsc, Arc, Mutex},
time::Duration,
time::Duration, sync::{Mutex, Arc, mpsc::channel},
};
use core::fmt::Debug;

use anyhow::Error;

Expand All @@ -14,84 +10,7 @@ use serde::{Deserialize, Deserializer};
use serde_json::Value;
use flowrs_std::{add::AddNode, debug::DebugNode, value::ValueNode};

#[derive(Clone)]
pub struct FlowType(pub Arc<dyn Any + Send + Sync>);

impl Debug for FlowType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(v) = self.0.downcast_ref::<f64>() {
return f.write_str(&v.to_string())
}
if let Some(v) = self.0.downcast_ref::<Value>() {
return match v {
Value::Null => todo!(),
Value::Bool(b) => f.write_str(&b.to_string()),
Value::Number(b) =>f.write_str(&b.to_string()),
Value::String(b) =>f.write_str(&b.to_string()),
_ => f.debug_tuple("FlowType").field(&self.0).finish(),
}
}
f.debug_tuple("FlowType").field(&self.0).finish()
}
}

// This implementation gives some control over which types should be
// addable throughout the entire flow. As of now only homogenious types
// allow addition.
// As the Properties of a Node can be any JSON value, the addition of
// such properties is limited to numbers (casted as float), lists and
// strings (both concatinated upon addition).
impl Add for FlowType {
type Output = FlowType;

fn add(self, rhs: Self) -> Self::Output {
if let Some(lhs) = self.0.downcast_ref::<i64>() {
if let Some(rhs) = rhs.0.downcast_ref::<i64>() {
return FlowType(Arc::new(lhs + rhs));
}
}
if let Some(lhs) = self.0.downcast_ref::<i32>() {
if let Some(rhs) = rhs.0.downcast_ref::<i32>() {
return FlowType(Arc::new(lhs + rhs));
}
}
if let Some(lhs) = self.0.downcast_ref::<String>() {
if let Some(rhs) = rhs.0.downcast_ref::<String>() {
let mut res = lhs.clone();
res.push_str(rhs);
return FlowType(Arc::new(res));
}
}
if let Some(lhs) = self.0.downcast_ref::<Value>() {
if let Some(rhs) = rhs.0.downcast_ref::<Value>() {
return match (lhs, rhs) {
(Value::Number(a), Value::Number(b)) => {
FlowType(Arc::new(a.as_f64().unwrap() + b.as_f64().unwrap()))
}
(Value::String(a), Value::String(b)) => {
let mut res = a.clone();
res.push_str(b);
FlowType(Arc::new(a.clone()))
}
(Value::Array(a), Value::Array(b)) => {
let mut res = a.clone();
res.append(b.to_owned().as_mut());
FlowType(Arc::new(a.clone()))
}
(a, b) => panic!(
"Addition of JSON values of type {:?} and {:?} is not supported.",
a, b
),
};
}
}
panic!(
"Addition not supported for type {:?} and {:?}.",
self.type_id(),
rhs.type_id()
);
}
}
use super::dynamic_flow::FlowType;

pub struct AppState {
// For a yet TBD reason a HashMap of dyn types looses track of channel pointers.
Expand Down Expand Up @@ -172,7 +91,7 @@ impl AppState {
}

pub fn run(self) {
let (sender, _) = mpsc::channel();
let (sender, _) = channel();
let node_map: HashMap<u128, Arc<Mutex<(dyn RuntimeNode + Send + 'static)>>> = self.nodes.into_iter().enumerate().map(|n| (n.0 as u128, n.1)).collect();
let flow = Flow::new("wasm", Version::new(0, 0, 1), node_map);
let node_updater = SingleThreadedNodeUpdater::new(None);
Expand Down
84 changes: 84 additions & 0 deletions src/flow/dynamic_flow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::ops::Add;
use std::{sync::Arc, any::Any};
use std::fmt::Debug;

use serde_json::Value;

#[derive(Clone)]
pub struct FlowType(pub Arc<dyn Any + Send + Sync>);

impl Debug for FlowType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(v) = self.0.downcast_ref::<f64>() {
return f.write_str(&v.to_string())
}
if let Some(v) = self.0.downcast_ref::<Value>() {
return match v {
Value::Null => todo!(),
Value::Bool(b) => f.write_str(&b.to_string()),
Value::Number(b) =>f.write_str(&b.to_string()),
Value::String(b) =>f.write_str(&b.to_string()),
_ => f.debug_tuple("FlowType").field(&self.0).finish(),
}
}
f.debug_tuple("FlowType").field(&self.0).finish()
}
}

// This implementation gives some control over which types should be
// addable throughout the entire flow. As of now only homogenious types
// allow addition.
// As the Properties of a Node can be any JSON value, the addition of
// such properties is limited to numbers (casted as float), lists and
// strings (both concatinated upon addition).
impl Add for FlowType {
type Output = FlowType;

fn add(self, rhs: Self) -> Self::Output {
if let Some(lhs) = self.0.downcast_ref::<i64>() {
if let Some(rhs) = rhs.0.downcast_ref::<i64>() {
return FlowType(Arc::new(lhs + rhs));
}
}
if let Some(lhs) = self.0.downcast_ref::<i32>() {
if let Some(rhs) = rhs.0.downcast_ref::<i32>() {
return FlowType(Arc::new(lhs + rhs));
}
}
if let Some(lhs) = self.0.downcast_ref::<String>() {
if let Some(rhs) = rhs.0.downcast_ref::<String>() {
let mut res = lhs.clone();
res.push_str(rhs);
return FlowType(Arc::new(res));
}
}
if let Some(lhs) = self.0.downcast_ref::<Value>() {
if let Some(rhs) = rhs.0.downcast_ref::<Value>() {
return match (lhs, rhs) {
(Value::Number(a), Value::Number(b)) => {
FlowType(Arc::new(a.as_f64().unwrap() + b.as_f64().unwrap()))
}
(Value::String(a), Value::String(b)) => {
let mut res = a.clone();
res.push_str(b);
FlowType(Arc::new(a.clone()))
}
(Value::Array(a), Value::Array(b)) => {
let mut res = a.clone();
res.append(b.to_owned().as_mut());
FlowType(Arc::new(a.clone()))
}
(a, b) => panic!(
"Addition of JSON values of type {:?} and {:?} is not supported.",
a, b
),
};
}
}
panic!(
"Addition not supported for type {:?} and {:?}.",
self.type_id(),
rhs.type_id()
);
}
}
1 change: 1 addition & 0 deletions src/flow/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod app_state;
pub mod dynamic_flow;
7 changes: 4 additions & 3 deletions tests/flow/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod app_state {
"#;

let json_data: AppState = serde_json::from_str(json_str).unwrap();
assert!(json_data.nodes.len() == 0);
assert_eq!(json_data.nodes.len(), 0);
}

#[test]
Expand Down Expand Up @@ -62,11 +62,12 @@ mod app_state {
}
"#;
let app_state: AppState = serde_json::from_str(json_str).unwrap();
assert!(app_state.nodes.len() == 4);
assert_eq!(app_state.nodes.len(), 4);
app_state.run();
}

#[test]
#[should_panic = r#"Addition of JSON values of type String("string") and Number(30) is not supported."#]
fn should_fail_on_invalid_types() {
let json_str = r#"
{
Expand Down Expand Up @@ -112,7 +113,7 @@ mod app_state {
"#;

let app_state: AppState = serde_json::from_str(json_str).unwrap();
assert!(app_state.nodes.len() == 4);
assert_eq!(app_state.nodes.len(), 4);
app_state.run();
}
}

0 comments on commit 0de9a7b

Please sign in to comment.