use std::{collections::HashMap, fmt};
use std::sync::Arc;
use std::str::FromStr;
use super::error::{Error, Result};
#[derive(Debug, Clone)]
pub struct ImplicitFunction {
pub id: u32,
pub identifier: String,
pub display_name: Option<String>,
pub r#in: Input,
pub out: Output,
pub nodes: Vec<Node>,
}
impl ImplicitFunction {
pub fn new(id: u32, identifier: impl Into<String>) -> Self {
Self {
id,
identifier: identifier.into(),
display_name: None,
r#in: Input::default(),
out: Output::default(),
nodes: Vec::new(),
}
}
pub fn set_input(&mut self, input: Input) -> &mut Self {
self.r#in = input;
self
}
pub fn set_output(&mut self, output: Output) -> &mut Self {
self.out = output;
self
}
pub fn add_node(&mut self, node: Node) -> &mut Self {
self.nodes.push(node);
self
}
pub fn get_node(&self, identifier: &str) -> Option<&Node> {
self.nodes.iter().find(|n| n.identifier == identifier)
}
}
#[derive(Debug, Clone, Default)]
pub struct Input {
pub values: Vec<Value>,
}
#[derive(Debug, Default, Clone)]
pub struct Output {
pub values: Vec<Value>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Value {
pub identifier: String,
pub display_name: Option<String>,
pub r#type: ValueType,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValueType {
Data(ValueData),
Ref(ValueRef),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValueData {
Scalar,
Vector,
Matrix,
ResourceId,
}
impl fmt::Display for ValueData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ValueData::Scalar => write!(f, "scalar"),
ValueData::Vector => write!(f, "vector"),
ValueData::Matrix => write!(f, "matrix"),
ValueData::ResourceId => write!(f, "resourceid"),
}
}
}
impl FromStr for ValueData {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_lowercase().as_str() {
"scalar" => Ok(ValueData::Scalar),
"vector" => Ok(ValueData::Vector),
"matrix" => Ok(ValueData::Matrix),
"resourceid" => Ok(ValueData::ResourceId),
_ => Err(Error::InvalidStructure(format!("unknown value data type: {}", s))),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValueRef {
ScalarRef(String),
VectorRef(String),
MatrixRef(String),
ResourceRef(String),
}
impl fmt::Display for ValueRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ValueRef::ScalarRef(r) => write!(f, "scalarref={}", r),
ValueRef::VectorRef(r) => write!(f, "vectorref={}", r),
ValueRef::MatrixRef(r) => write!(f, "matrixref={}", r),
ValueRef::ResourceRef(r) => write!(f, "resourceref={}", r),
}
}
}
impl FromStr for ValueRef {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
let vs = s.split('=').collect::<Vec<_>>();
if vs.len() == 2 {
match vs[0].to_lowercase().as_str() {
"scalarref" => Ok(ValueRef::ScalarRef(vs[1].to_string())),
"vectorref" => Ok(ValueRef::VectorRef(vs[1].to_string())),
"matrixref" => Ok(ValueRef::MatrixRef(vs[1].to_string())),
"resourceref" => Ok(ValueRef::ResourceRef(vs[1].to_string())),
_ => Err(Error::InvalidStructure(format!("unknown value ref type: {}", s))),
}
} else {
Err(Error::InvalidStructure(format!("invalid value ref format: {}", s)))
}
}
}
#[derive(Debug, Clone)]
pub struct Node {
pub identifier: String,
pub display_name: Option<String>,
pub tag: Option<String>,
pub r#type: Arc<Box<dyn NodeType>>,
pub r#in: Input,
pub out: Output,
}
impl Node {
pub fn new<T: NodeType + 'static>(identifier: impl Into<String>, r#type: T) -> Self {
Self {
identifier: identifier.into(),
display_name: None,
tag: None,
r#type: Arc::new(Box::new(r#type)),
r#in: Input::default(),
out: Output::default(),
}
}
pub fn set_display_name(&mut self, name: impl Into<String>) -> &mut Self {
self.display_name = Some(name.into());
self
}
pub fn set_tag(&mut self, tag: impl Into<String>) -> &mut Self {
self.tag = Some(tag.into());
self
}
pub fn set_input(&mut self, input: Input) -> &mut Self {
self.r#in = input;
self
}
pub fn set_output(&mut self, output: Output) -> &mut Self {
self.out = output;
self
}
}
pub trait NodeType: fmt::Display + fmt::Debug {
fn name(&self) -> String {
self.to_string()
}
}
#[derive(Debug, Clone)]
pub struct Addition;
impl NodeType for Addition {}
impl fmt::Display for Addition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "addition")
}
}
#[derive(Debug, Clone)]
pub struct Subtraction;
impl NodeType for Subtraction {}
impl fmt::Display for Subtraction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "subtraction")
}
}
#[derive(Debug, Clone)]
pub struct Multiplication;
impl NodeType for Multiplication {}
impl fmt::Display for Multiplication {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "multiplication")
}
}
#[derive(Debug, Clone)]
pub struct Division;
impl NodeType for Division {}
impl fmt::Display for Division {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "division")
}
}
#[derive(Debug, Clone)]
pub struct Constant { value: f64 }
impl Constant {
pub fn new(value: f64) -> Self {
Self { value }
}
}
impl NodeType for Constant {
fn name(&self) -> String {
"constant".to_string()
}
}
impl fmt::Display for Constant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}|value={}", self.name(), self.value)
}
}
#[derive(Debug, Clone)]
pub struct ConstVec { x: f64, y: f64, z: f64 }
impl ConstVec {
pub fn new(x: f64, y: f64, z: f64) -> Self {
Self { x, y, z }
}
}
impl NodeType for ConstVec {
fn name(&self) -> String {
"constvec".to_string()
}
}
impl fmt::Display for ConstVec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}|x={}|y={}|z={}", self.name(), self.x, self.y, self.z)
}
}
#[derive(Debug, Clone)]
pub struct ConstMat { matrix: [f64; 16] }
impl ConstMat {
pub fn new(matrix: [f64; 16]) -> Self {
Self { matrix }
}
}
impl NodeType for ConstMat {
fn name(&self) -> String {
"constmat".to_string()
}
}
impl fmt::Display for ConstMat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}|matrix={}", self.name(), self.matrix.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(" "))
}
}
#[derive(Debug, Clone)]
pub struct ConstResourceId { value: u32 }
impl ConstResourceId {
pub fn new(value: u32) -> Self {
Self { value }
}
}
impl NodeType for ConstResourceId {
fn name(&self) -> String {
"constresourceid".to_string()
}
}
impl fmt::Display for ConstResourceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}|value={}", self.name(), self.value)
}
}
#[derive(Debug, Clone)]
pub struct ComposeVector;
impl NodeType for ComposeVector {}
impl fmt::Display for ComposeVector {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "composevector")
}
}
#[derive(Debug, Clone)]
pub struct VectorFromScalar;
impl NodeType for VectorFromScalar {}
impl fmt::Display for VectorFromScalar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "vectorfromscalar")
}
}
#[derive(Debug, Clone)]
pub struct DecomposeVector;
impl NodeType for DecomposeVector {}
impl fmt::Display for DecomposeVector {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "decomposevector")
}
}
#[derive(Debug, Clone)]
pub struct ComposeMatrix;
impl NodeType for ComposeMatrix {}
impl fmt::Display for ComposeMatrix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "composematrix")
}
}
#[derive(Debug, Clone)]
pub struct MatrixFromColumns;
impl NodeType for MatrixFromColumns {}
impl fmt::Display for MatrixFromColumns {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "matrixfromcolumns")
}
}
#[derive(Debug, Clone)]
pub struct MatrixFromRows;
impl NodeType for MatrixFromRows {}
impl fmt::Display for MatrixFromRows {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "matrixfromrows")
}
}
#[derive(Debug, Clone)]
pub struct Dot;
impl NodeType for Dot {}
impl fmt::Display for Dot {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "dot")
}
}
#[derive(Debug, Clone)]
pub struct Cross;
impl NodeType for Cross {}
impl fmt::Display for Cross {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "cross")
}
}
#[derive(Debug, Clone)]
pub struct MatrixVectorMultiplication;
impl NodeType for MatrixVectorMultiplication {}
impl fmt::Display for MatrixVectorMultiplication {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "matrixvectormultiplication")
}
}
#[derive(Debug, Clone)]
pub struct Transpose;
impl NodeType for Transpose {}
impl fmt::Display for Transpose {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "transpose")
}
}
#[derive(Debug, Clone)]
pub struct Inverse;
impl NodeType for Inverse {}
impl fmt::Display for Inverse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "inverse")
}
}
#[derive(Debug, Clone)]
pub struct Sin;
impl NodeType for Sin {}
impl fmt::Display for Sin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "sin")
}
}
#[derive(Debug, Clone)]
pub struct Cos;
impl NodeType for Cos {}
impl fmt::Display for Cos {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "cos")
}
}
#[derive(Debug, Clone)]
pub struct Tan;
impl NodeType for Tan {}
impl fmt::Display for Tan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "tan")
}
}
#[derive(Debug, Clone)]
pub struct Asin;
impl NodeType for Asin {}
impl fmt::Display for Asin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "asin")
}
}
#[derive(Debug, Clone)]
pub struct Acos;
impl NodeType for Acos {}
impl fmt::Display for Acos {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "acos")
}
}
#[derive(Debug, Clone)]
pub struct Atan;
impl NodeType for Atan {}
impl fmt::Display for Atan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "atan")
}
}
#[derive(Debug, Clone)]
pub struct Atan2;
impl NodeType for Atan2 {}
impl fmt::Display for Atan2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "atan2")
}
}
#[derive(Debug, Clone)]
pub struct Min;
impl NodeType for Min {}
impl fmt::Display for Min {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "min")
}
}
#[derive(Debug, Clone)]
pub struct Max;
impl NodeType for Max {}
impl fmt::Display for Max {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "max")
}
}
#[derive(Debug, Clone)]
pub struct Abs;
impl NodeType for Abs {}
impl fmt::Display for Abs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "abs")
}
}
#[derive(Debug, Clone)]
pub struct Fmod;
impl NodeType for Fmod {}
impl fmt::Display for Fmod {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "fmod")
}
}
#[derive(Debug, Clone)]
pub struct Mod;
impl NodeType for Mod {}
impl fmt::Display for Mod {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "mod")
}
}
#[derive(Debug, Clone)]
pub struct Pow;
impl NodeType for Pow {}
impl fmt::Display for Pow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "pow")
}
}
#[derive(Debug, Clone)]
pub struct Sqrt;
impl NodeType for Sqrt {}
impl fmt::Display for Sqrt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "sqrt")
}
}
#[derive(Debug, Clone)]
pub struct Exp;
impl NodeType for Exp {}
impl fmt::Display for Exp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "exp")
}
}
#[derive(Debug, Clone)]
pub struct Log;
impl NodeType for Log {}
impl fmt::Display for Log {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "log")
}
}
#[derive(Debug, Clone)]
pub struct Log2;
impl NodeType for Log2 {}
impl fmt::Display for Log2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "log2")
}
}
#[derive(Debug, Clone)]
pub struct Log10;
impl NodeType for Log10 {}
impl fmt::Display for Log10 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "log10")
}
}
#[derive(Debug, Clone)]
pub struct Select;
impl NodeType for Select {}
impl fmt::Display for Select {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "select")
}
}
#[derive(Debug, Clone)]
pub struct Clamp;
impl NodeType for Clamp {}
impl fmt::Display for Clamp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "clamp")
}
}
#[derive(Debug, Clone)]
pub struct Cosh;
impl NodeType for Cosh {}
impl fmt::Display for Cosh {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "cosh")
}
}
#[derive(Debug, Clone)]
pub struct Sinh;
impl NodeType for Sinh {}
impl fmt::Display for Sinh {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "sinh")
}
}
#[derive(Debug, Clone)]
pub struct Tanh;
impl NodeType for Tanh {}
impl fmt::Display for Tanh {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "tanh")
}
}
#[derive(Debug, Clone)]
pub struct Round;
impl NodeType for Round {}
impl fmt::Display for Round {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "round")
}
}
#[derive(Debug, Clone)]
pub struct Ceil;
impl NodeType for Ceil {}
impl fmt::Display for Ceil {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ceil")
}
}
#[derive(Debug, Clone)]
pub struct Floor;
impl NodeType for Floor {}
impl fmt::Display for Floor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "floor")
}
}
#[derive(Debug, Clone)]
pub struct Sign;
impl NodeType for Sign {}
impl fmt::Display for Sign {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "sign")
}
}
#[derive(Debug, Clone)]
pub struct Fract;
impl NodeType for Fract {}
impl fmt::Display for Fract {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "fract")
}
}
#[derive(Debug, Clone)]
pub struct Length;
impl NodeType for Length {}
impl fmt::Display for Length {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "length")
}
}
#[derive(Debug, Clone)]
pub struct FunctionGradient {
scalar_output: String,
vector_input: String,
}
impl NodeType for FunctionGradient {
fn name(&self) -> String {
"functiongradient".to_string()
}
}
impl fmt::Display for FunctionGradient {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}|scalaroutput={}|vectorinput={}", self.name(), self.scalar_output, self.vector_input)
}
}
#[derive(Debug, Clone)]
pub struct NormalizeDistance {
scalar_output: String,
vector_input: String,
}
impl NodeType for NormalizeDistance {
fn name(&self) -> String {
"normalizedistance".to_string()
}
}
impl fmt::Display for NormalizeDistance {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}|scalaroutput={}|vectorinput={}", self.name(), self.scalar_output, self.vector_input)
}
}
#[derive(Debug, Clone)]
pub struct FunctionCall;
impl NodeType for FunctionCall {}
impl fmt::Display for FunctionCall {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "functioncall")
}
}
#[derive(Debug, Clone)]
pub struct SignedMesh;
impl NodeType for SignedMesh {}
impl fmt::Display for SignedMesh {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "mesh")
}
}
#[derive(Debug, Clone)]
pub struct UnsignedMesh;
impl NodeType for UnsignedMesh {}
impl fmt::Display for UnsignedMesh {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "unsignedmesh")
}
}
#[derive(Debug, Clone)]
pub struct BeamLattice {
accurate_range: Option<f64>,
}
impl NodeType for BeamLattice {
fn name(&self) -> String {
"beamlattice".to_string()
}
}
impl fmt::Display for BeamLattice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(range) = self.accurate_range {
write!(f, "{}|accuraterange={}", self.name(), range)
} else {
write!(f, "{}", self.name())
}
}
}
impl FromStr for Box<dyn NodeType> {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
let vs = s.split('|').collect::<Vec<_>>();
let make = || {
let mut kvs = HashMap::new();
for v in vs[1..].iter() {
let vs = v.split("=").collect::<Vec<_>>();
if vs.len() == 2 {
kvs.insert(vs[0].to_string(), vs[1].to_string());
}
}
kvs
};
let pick = |k: &str, kvs: &HashMap<String, String>| {
kvs.get(k).map(|v| v.clone()).unwrap_or_default()
};
if vs.len() >= 1 {
match vs[0] {
"addition" => Ok(Box::new(Addition)),
"subtraction" => Ok(Box::new(Subtraction)),
"multiplication" => Ok(Box::new(Multiplication)),
"division" => Ok(Box::new(Division)),
"constant" => Ok(Box::new(Constant { value: pick("value", &make()).parse()? })),
"constvec" => {
let kvs = make();
Ok(Box::new(ConstVec { x: pick("x", &kvs).parse()?, y: pick("y", &kvs).parse()?, z: pick("z", &kvs).parse()? }))
},
"constmat" => {
let x = pick("matrix", &make())
.split_whitespace()
.map(|v| v.parse::<f64>())
.collect::<std::result::Result<Vec<_>, _>>()
.map_err(|_| Error::InvalidMatrix(format!("cannot parse matrix: {}", s)))?;
let m = [
x[0], x[1], x[2], x[3],
x[4], x[5], x[6], x[7],
x[8], x[9], x[10], x[11],
x[12], x[13], x[14], x[15],
];
Ok(Box::new(ConstMat { matrix: m }))
},
"constresourceid" => Ok(Box::new(ConstResourceId { value: pick("value", &make()).parse()? })),
"composevector" => Ok(Box::new(ComposeVector)),
"vectorfromscalar" => Ok(Box::new(VectorFromScalar)),
"decomposevector" => Ok(Box::new(DecomposeVector)),
"composematrix" => Ok(Box::new(ComposeMatrix)),
"matrixfromcolumns" => Ok(Box::new(MatrixFromColumns)),
"matrixfromrows" => Ok(Box::new(MatrixFromRows)),
"dot" => Ok(Box::new(Dot)),
"cross" => Ok(Box::new(Cross)),
"matrixvectormultiplication" => Ok(Box::new(MatrixVectorMultiplication)),
"transpose" => Ok(Box::new(Transpose)),
"inverse" => Ok(Box::new(Inverse)),
"sin" => Ok(Box::new(Sin)),
"cos" => Ok(Box::new(Cos)),
"tan" => Ok(Box::new(Tan)),
"asin" => Ok(Box::new(Asin)),
"acos" => Ok(Box::new(Acos)),
"atan" => Ok(Box::new(Atan)),
"atan2" => Ok(Box::new(Atan2)),
"min" => Ok(Box::new(Min)),
"max" => Ok(Box::new(Max)),
"abs" => Ok(Box::new(Abs)),
"fmod" => Ok(Box::new(Fmod)),
"mod" => Ok(Box::new(Mod)),
"pow" => Ok(Box::new(Pow)),
"sqrt" => Ok(Box::new(Sqrt)),
"exp" => Ok(Box::new(Exp)),
"log" => Ok(Box::new(Log)),
"log2" => Ok(Box::new(Log2)),
"log10" => Ok(Box::new(Log10)),
"select" => Ok(Box::new(Select)),
"clamp" => Ok(Box::new(Clamp)),
"cosh" => Ok(Box::new(Cosh)),
"sinh" => Ok(Box::new(Sinh)),
"tanh" => Ok(Box::new(Tanh)),
"round" => Ok(Box::new(Round)),
"ceil" => Ok(Box::new(Ceil)),
"floor" => Ok(Box::new(Floor)),
"sign" => Ok(Box::new(Sign)),
"fract" => Ok(Box::new(Fract)),
"length" => Ok(Box::new(Length)),
"functiongradient" => {
let kvs = make();
Ok(Box::new(FunctionGradient {
scalar_output: pick("scalaroutput", &kvs),
vector_input: pick("vectorinput", &kvs),
}))
}
"normalizedistance" => {
let kvs = make();
Ok(Box::new(NormalizeDistance {
scalar_output: pick("scalaroutput", &kvs),
vector_input: pick("vectorinput", &kvs),
}))
},
"functioncall" => Ok(Box::new(FunctionCall)),
"mesh" => Ok(Box::new(SignedMesh)),
"unsignedmesh" => Ok(Box::new(UnsignedMesh)),
"beamlattice" => {
let range = if let Some(range) = make().get("accuraterange") {
Some(range.parse::<f64>()?)
} else {
None
};
Ok(Box::new(BeamLattice { accurate_range: range }))
},
_ => Err(Error::InvalidStructure(format!("unknown function node type: {}", s))),
}
} else {
Err(Error::InvalidStructure(format!("invalid function node type: {}", s)))
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ImplicitResources {
pub functions: Vec<ImplicitFunction>,
}
impl ImplicitResources {
pub fn new() -> Self {
Self::default()
}
}