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
//! Definition of the current state of the graph modeled in the UI.
//!
//! # Example
//!
//! The following example represents a possible report returned from an
//! application instantiated via the [`Config`
//! example](../config/index.html#example). Note that it is not a valid rust
//! code, but an output of the `dbg!` macro.
//!
//! ```ignore
//! Report {
//!     nodes: [
//!         Node {
//!             id: "comment:0",
//!             class: "comment",
//!             data: {
//!                 "comment": String(
//!                     "Content of the comment block.",
//!                 ),
//!             },
//!         },
//!         Node {
//!             id: "oscillator:0",
//!             class: "oscillator",
//!             data: {
//!                 "switch": Bool(
//!                     true,
//!                 ),
//!                 "trigger": Bool(
//!                     false,
//!                 ),
//!                 "dropdown": String(
//!                     "triangle",
//!                 ),
//!                 "slider": F32(
//!                     7.5,
//!                 ),
//!             },
//!         },
//!         Node {
//!             id: "mixer:0",
//!             class: "mixer",
//!             data: {},
//!         },
//!     ],
//!     patches: [
//!         Patch {
//!             source: PinAddress {
//!                 node_id: "oscillator:0",
//!                 pin_class: "output",
//!             },
//!             destination: PinAddress {
//!                 node_id: "mixer:0",
//!                 pin_class: "input1",
//!             },
//!         },
//!     ],
//! }
//! ```

use std::collections::HashMap;

/// Report is a structure holding information about the current "model" of the
/// graph represented in the UI. It does not report details about the widgets
/// that were used nor about positions of items on the canvas. It is limited to
/// the minimal amount of information needed to convert the state into a graph.
#[derive(Debug)]
pub struct Report {
    /// All instantiated notes with their values set via widgets.
    pub nodes: Vec<Node>,
    /// List of all patches connecting node pins.
    pub patches: Vec<Patch>,
}

/// A structure representing an existing node and its associated values.
#[derive(Debug)]
pub struct Node {
    /// Unique identificator of this node.
    pub id: String,
    /// Class references the node template this node was instantiated from.
    pub class: String,
    /// Map of all the values set via widgets available on the node. The key is
    /// always the key of the given widget as defined in the node template.
    pub data: HashMap<String, Value>,
}

/// Enum encapsulating possible values of an item attached to a node.
#[derive(Debug)]
pub enum Value {
    String(String),
    F32(f32),
    Bool(bool),
}

impl Value {
    /// Access string value stored in the enum.
    ///
    /// # Panics
    ///
    /// Panics if the variant is not `String`.
    pub fn unwrap_string(&self) -> &str {
        if let Self::String(value) = self {
            &value
        } else {
            panic!("The value is not of type String");
        }
    }

    /// Access f32 value stored in the enum.
    ///
    /// # Panics
    ///
    /// Panics if the variant is not `F32`.
    pub fn unwrap_f32(&self) -> f32 {
        if let Self::F32(value) = self {
            *value
        } else {
            panic!("The value is not of type F32");
        }
    }

    /// Access bool value stored in the enum.
    ///
    /// # Panics
    ///
    /// Panics if the variant is not `Bool`.
    pub fn unwrap_bool(&self) -> bool {
        if let Self::Bool(value) = self {
            *value
        } else {
            panic!("The value is not of type Bool");
        }
    }
}

/// A structure representing a patch between two pins of available nodes.
#[derive(Debug)]
pub struct Patch {
    /// Output pin where the patch originates from.
    pub source: PinAddress,
    /// Input pin where the patch leads into.
    pub destination: PinAddress,
}

/// Uniquely represents a pin by referencing node by its ID an pin by
/// its class.
#[derive(Debug)]
pub struct PinAddress {
    pub node_id: String,
    pub pin_class: String,
}