1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use std::cell::{Cell, RefCell};
use crate::prelude::*;
use juiz_sdk::{connection_identifier::ConnectionIdentifier, connections::ConnectionProfile};
/// inlet.rs
///
///
///
pub struct Inlet {
name: String,
source_connections: Vec<Box<dyn SourceConnection>>,
default_value: CapsulePtr,
buffer: RefCell<Option<CapsulePtr>>,
/// bind (p_apply) で値が設定されてから、まだ collect_value で読まれていないとき true
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_connection_by_identifier(&mut self, identifier: &Identifier) -> Option<&Box<dyn SourceConnection>> {
// for c in self.source_connections.iter() {
// if c.identifier() == identifier {
// return Some(c)
// }
// }
// return None
// }
pub fn source_connections(&self) -> &Vec<Box<dyn SourceConnection>> {
return &self.source_connections;
}
// pub fn source_connections_mut(&mut self) -> &mut Vec<Box<dyn SourceConnection>> {
// return &mut 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())
}
/// 次の実行で使われる値 (p_apply で拘束した値か、push で届いた値)。
/// まだ無いときと、値型でない (画像など) ときは None (issue #112)
pub fn current_value(&self) -> Option<Value> {
self.buffer
.borrow()
.as_ref()
.and_then(|c| c.lock_as_value(|v| v.clone()).ok())
}
pub fn is_updated(&self) -> JuizResult<bool> {
if self.updated.get() {
return Ok(true);
}
//self.source_connections.iter().find_map(|sc| { if sc.is_source_updated() })
for sc in self.source_connections.iter() {
if sc.is_source_updated()? {
return Ok(true);
}
}
Ok(false)
}
/// データを収集。
///
/// まず全てのコネクションに対してpullでデータ収集を行う。
/// 出力はself.bufferに保存されるため、あとからの接続が優先される。
/// エラーはログは出すが無視する。
/// 接続が無いか、全ての接続がPull型ではないか、もしくはPull型接続をpullしてもエラーがあった場合、
/// self.bufferを確認する。bufferがNoneならばデフォルトの値を出力する。
/// bufferにデータが残っていればそれを返す。
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()));
//return self.buffer.borrow().unwrap().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())
}
/// push 接続で届いた値をバッファに保存する。
///
/// p_apply と同じバッファに書くので、後から来た値が次の execute で使われる (issue #70)。
/// 届いた値ですぐ計算するため、updated フラグは立てない。
pub fn store(&self, value: CapsulePtr) {
self.buffer.replace(Some(value));
}
pub fn bind(&mut self, value: CapsulePtr) -> JuizResult<CapsulePtr> {
// 後から設定した値で上書きし、次の invoke でメモを使わずに再計算させる (issue #18)
self.buffer.replace(Some(value.clone()));
self.updated.set(true);
Ok(value)
}
}