use libhaystack::val::Value;
use serde::{Deserialize, Serialize};
use crate::base::{
block::{BlockDesc, BlockPin, desc::BlockImplementation},
engine::messages::{ChangeSource, WatchMessage},
};
#[derive(Default, Clone, Serialize, Deserialize)]
pub struct JsBlockPin {
pub name: String,
pub kind: String,
}
#[derive(Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JsBlockDesc {
pub name: String,
pub dis: String,
pub lib: String,
pub ver: String,
pub category: String,
pub doc: String,
pub implementation: String,
pub inputs: Vec<JsBlockPin>,
pub outputs: Vec<JsBlockPin>,
pub run_condition: Option<String>,
}
impl From<JsBlockDesc> for BlockDesc {
fn from(desc: JsBlockDesc) -> Self {
Self {
name: desc.name,
dis: desc.dis,
library: desc.lib,
ver: desc.ver,
category: desc.category,
doc: desc.doc,
implementation: BlockImplementation::External,
inputs: desc
.inputs
.into_iter()
.map(|pin| BlockPin {
name: pin.name,
kind: pin.kind.as_str().try_into().unwrap_or_default(),
})
.collect(),
outputs: desc
.outputs
.into_iter()
.map(|pin| BlockPin {
name: pin.name,
kind: pin.kind.as_str().try_into().unwrap_or_default(),
})
.collect(),
run_condition: desc
.run_condition
.map(|cond| cond.as_str().try_into().unwrap_or_default()),
}
}
}
impl From<BlockDesc> for JsBlockDesc {
fn from(desc: BlockDesc) -> Self {
Self {
name: desc.name,
dis: desc.dis,
lib: desc.library,
ver: desc.ver,
category: desc.category,
doc: desc.doc,
implementation: desc.implementation.to_string(),
inputs: desc
.inputs
.into_iter()
.map(|pin| JsBlockPin {
name: pin.name,
kind: pin.kind.to_string(),
})
.collect(),
outputs: desc
.outputs
.into_iter()
.map(|pin| JsBlockPin {
name: pin.name,
kind: pin.kind.to_string(),
})
.collect(),
run_condition: desc.run_condition.map(|cond| cond.to_string()),
}
}
}
#[derive(Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JsWatchNotification {
pub id: String,
pub changes: Vec<JsWatchChange>,
pub state: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub fault_reason: Option<String>,
}
#[derive(Default, Serialize, Deserialize)]
pub struct JsWatchChange {
pub name: String,
pub source: String,
pub value: Value,
}
impl From<WatchMessage> for JsWatchNotification {
fn from(msg: WatchMessage) -> Self {
let block_id = msg.block_id.to_string();
let state = msg.state.label().to_string();
let fault_reason = msg.state.fault_reason().map(|s| s.to_string());
let changes = msg
.changes
.into_iter()
.map(|(name, source)| JsWatchChange {
name,
source: match source {
ChangeSource::Input(_, _) => "input".to_string(),
ChangeSource::Output(_, _) => "output".to_string(),
},
value: match source {
ChangeSource::Input(_, v) => v,
ChangeSource::Output(_, v) => v,
},
})
.collect();
Self {
id: block_id,
changes,
state,
fault_reason,
}
}
}