Newer
Older
use crate::analyzer::AnalyzerType;
use crate::dottable::Dottable;
use crate::error::OpossumError;
use crate::nodes::{create_node_ref, Dummy, NodeGroup};
use petgraph::prelude::DiGraph;
use petgraph::stable_graph::NodeIndex;
use serde::de::{self, Deserialize, MapAccess, SeqAccess, Visitor};
use serde::ser::SerializeStruct;
use serde::Serialize;
pub type LightResult = HashMap<String, Option<LightData>>;
type Result<T> = std::result::Result<T, OpossumError>;
/// This is the basic trait that must be implemented by all concrete optical components.
/// Sets the name of this [`Optical`].
fn set_name(&mut self, _name: &str) {}
/// Returns a reference to the name of this [`Optical`].
fn name(&self) -> &str {
/// Return the type of the optical component (lens, filter, ...).
fn node_type(&self) -> &str;
/// Return the available (input & output) ports of this [`Optical`].
fn ports(&self) -> OpticPorts {
OpticPorts::default()
}
/// Perform an analysis of this element. The type of analysis is given by an [`AnalyzerType`].
///
/// This function is normally only called by [`OpticScenery::analyze()`](crate::optic_scenery::OpticScenery::analyze()).
///
/// # Errors
///
/// This function will return an error if internal element-specific errors occur and the analysis cannot be performed.
fn analyze(
&mut self,
_incoming_data: LightResult,
_analyzer_type: &AnalyzerType,
) -> Result<LightResult> {
print!("{}: No analyze function defined.", self.node_type());
Ok(LightResult::default())
}
/// Export analysis data to file with the given name.
fn export_data(&self, _file_name: &str) {
println!(
"no export_data function implemented for nodetype <{}>",
self.node_type()
)
}
/// Returns `true` if the [`Optical`] represents a detector which can report analysis data.
fn is_detector(&self) -> bool {
false
}
/// Mark this [`Optical`] as inverted.
fn set_inverted(&mut self, _inverted: bool) {
// self.ports.set_inverted(inverted);
// self.node.set_inverted(inverted);
}
/// Returns `true` if this [`Optical`] is inverted.
fn inverted(&self) -> bool {
false
}
fn as_group(&self) -> Result<&NodeGroup> {
Err(OpossumError::Other("cannot cast to group".into()))
}
fn set_property(&mut self, _name: &str, _prop: Property) -> Result<()> {
Ok(())
}
fn set_properties(&mut self, properties: &Properties) -> Result<()> {
let own_properties= self.properties().props.clone();
for prop in properties.props.iter() {
if own_properties.contains_key(prop.0) {
self.set_property(prop.0, prop.1.clone())?;
}
}
Ok(())
}
}
impl Debug for dyn Optical {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
#[derive(Debug, Default, Clone)]
pub struct OpticGraph(pub DiGraph<OpticRef, Light>);
impl Serialize for OpticGraph {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let g = self.0.clone();
let mut graph = serializer.serialize_struct("graph", 2)?;
let nodes = g
.node_weights()
.map(|n| n.to_owned())
.collect::<Vec<OpticRef>>();
graph.serialize_field("nodes", &nodes)?;
let edgeidx = g
.edge_indices()
.map(|e| {
(
g.edge_endpoints(e).unwrap().0,
g.edge_endpoints(e).unwrap().1,
g.edge_weight(e).unwrap().src_port(),
g.edge_weight(e).unwrap().target_port(),
)
})
.collect::<Vec<(NodeIndex, NodeIndex, &str, &str)>>();
graph.serialize_field("edges", &edgeidx)?;
#[derive(Debug, Clone)]
pub struct OpticRef(pub Rc<RefCell<dyn Optical>>);
impl Serialize for OpticRef {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut node = serializer.serialize_struct("node", 1)?;
node.serialize_field("type", self.0.borrow().node_type())?;
node.serialize_field("properties", &self.0.borrow().properties())?;
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
impl<'de> Deserialize<'de> for OpticRef {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
enum Field {
NodeType,
Properties,
}
const FIELDS: &'static [&'static str] = &["type", "properties"];
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("`type` or `properties`")
}
fn visit_str<E>(self, value: &str) -> std::result::Result<Field, E>
where
E: de::Error,
{
match value {
"type" => Ok(Field::NodeType),
"properties" => Ok(Field::Properties),
_ => Err(de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct OpticRefVisitor;
impl<'de> Visitor<'de> for OpticRefVisitor {
type Value = OpticRef;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a struct OpticRef")
}
fn visit_seq<A>(self, mut seq: A) -> std::result::Result<OpticRef, A::Error>
where
A: SeqAccess<'de>,
{
let _node_type = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let _properties = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
Ok(OpticRef(Rc::new(RefCell::new(Dummy::default()))))
}
fn visit_map<A>(self, mut map: A) -> std::result::Result<OpticRef, A::Error>
where
A: MapAccess<'de>,
{
let mut node_type = None;
let mut properties = None;
while let Some(key) = map.next_key()? {
match key {
Field::NodeType => {
if node_type.is_some() {
return Err(de::Error::duplicate_field("type"));
}
node_type = Some(map.next_value()?);
}
Field::Properties => {
if properties.is_some() {
return Err(de::Error::duplicate_field("properties"));
}
properties = Some(map.next_value::<Properties>()?);
let node_type = node_type.ok_or_else(|| de::Error::missing_field("type"))?;
let properties =
properties.ok_or_else(|| de::Error::missing_field("properties"))?;
let node =
create_node_ref(node_type).map_err(|e| de::Error::custom(e.to_string()))?;
node.0
.borrow_mut()
.set_properties(&properties).map_err(|e| de::Error::custom(e.to_string()))?;
Ok(node)
}
}
deserializer.deserialize_struct("OpticRef", FIELDS, OpticRefVisitor)
}