use std::cell::{Cell, RefCell};
use crate::prelude::*;
use juiz_sdk::{connection_identifier::ConnectionIdentifier, connections::ConnectionProfile};
pub struct Inlet {
name: String,
source_connections: Vec<Box<dyn SourceConnection>>,
default_value: CapsulePtr,
buffer: RefCell<Option<CapsulePtr>>,
updated: Cell<bool>,
}
impl std::fmt::Debug for Inlet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Inlet")
.field("name", &self.name)
.field("default_value", &self.default_value)
.field("buffer", &self.buffer)
.finish()
}
}
impl Inlet {
pub fn new(name: &str, default_value: Value) -> Inlet {
Inlet {
name: name.to_owned(),
default_value: default_value.into(),
source_connections: Vec::new(),
buffer: RefCell::new(None),
updated: Cell::new(false),
}
}
pub fn name(&self) -> &String {
&self.name
}
pub fn source_connections(&self) -> &Vec<Box<dyn SourceConnection>> {
return &self.source_connections;
}
#[allow(unused)]
pub fn profile_full(&self) -> JuizResult<Value> {
Ok(jvalue!({
"name": self.name,
"source_connections": self.source_connections.iter().map(|sc| -> Value {
sc.profile().into()
}).collect::<Vec<Value>>()
})
.into())
}
pub fn is_updated(&self) -> JuizResult<bool> {
if self.updated.get() {
return Ok(true);
}
for sc in self.source_connections.iter() {
if sc.is_source_updated()? {
return Ok(true);
}
}
Ok(false)
}
pub fn collect_value(&self) -> CapsulePtr {
log::trace!("Inlet({})::collect_value() called", self.name());
self.updated.set(false);
for sc in self.source_connections.iter() {
if sc.connection_type() == ConnectionType::Pull {
match sc.pull() {
Err(e) => {
log::error!("Pull data via Connection({}) in Inlet({})::collect_value() failed. Error: {:}", sc.identifier(), self.name(), e);
}
Ok(output) => {
self.buffer.replace(Some(output.clone()));
}
}
}
}
if self.buffer.borrow().is_none() {
self.default_value.clone()
} else {
self.buffer.borrow().clone().unwrap()
}
}
pub(crate) fn insert(&mut self, con: Box<dyn SourceConnection + 'static>) {
self.source_connections.push(con);
}
pub(crate) fn remove(&mut self, id: &ConnectionIdentifier) -> Option<ConnectionProfile> {
let index = self
.source_connections
.iter()
.position(|c| c.identifier().is_same_connection(id))?;
Some(self.source_connections.remove(index).profile())
}
pub fn bind(&mut self, value: CapsulePtr) -> JuizResult<CapsulePtr> {
self.buffer.replace(Some(value.clone()));
self.updated.set(true);
Ok(value)
}
}