melodium_share/
collection.rs1use crate::{Context, Data, Function, Identifier, Model, Treatment};
2use itertools::Itertools;
3use melodium_common::descriptor::{
4 Collection as CommonCollection, Entry, Identified, Identifier as CommonIdentifier,
5};
6use serde::{Deserialize, Serialize};
7use std::collections::VecDeque;
8
9#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11#[cfg_attr(feature = "webassembly", derive(tsify::Tsify))]
12#[cfg_attr(feature = "webassembly", tsify(into_wasm_abi, from_wasm_abi))]
13pub enum Element {
14 Context(Context),
15 Data(Data),
16 Function(Function),
17 Model(Model),
18 Treatment(Treatment),
19}
20
21impl Element {
22 pub fn identifier(&self) -> &Identifier {
23 match self {
24 Element::Context(c) => &c.identifier,
25 Element::Data(d) => &d.identifier,
26 Element::Function(f) => &f.identifier,
27 Element::Model(m) => &m.identifier,
28 Element::Treatment(t) => &t.identifier,
29 }
30 }
31
32 pub fn is_compiled(&self) -> bool {
33 match self {
34 Element::Context(_) => true,
35 Element::Data(_) => true,
36 Element::Function(_) => true,
37 Element::Model(m) => m.implementation_kind.is_compiled(),
38 Element::Treatment(t) => t.implementation_kind.is_compiled(),
39 }
40 }
41}
42
43impl From<&Entry> for Element {
44 fn from(value: &Entry) -> Self {
45 match value {
46 Entry::Context(c) => Element::Context(c.as_ref().into()),
47 Entry::Data(d) => Element::Data(d.as_ref().into()),
48 Entry::Function(f) => Element::Function(f.as_ref().into()),
49 Entry::Model(m) => Element::Model(m.into()),
50 Entry::Treatment(t) => Element::Treatment(t.into()),
51 }
52 }
53}
54
55#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
56#[cfg_attr(feature = "webassembly", derive(tsify::Tsify))]
57#[cfg_attr(feature = "webassembly", tsify(into_wasm_abi, from_wasm_abi))]
58pub struct Collection {
59 elements: Vec<Element>,
60}
61
62impl Collection {
63 pub fn elements(&self) -> &Vec<Element> {
64 &self.elements
65 }
66
67 pub fn to_elements(self) -> Vec<Element> {
68 self.elements
69 }
70
71 pub fn from_entrypoint(collection: &CommonCollection, entrypoint: &CommonIdentifier) -> Self {
72 let mut identifiers: VecDeque<CommonIdentifier> = VecDeque::new();
73
74 if let Some(element) = collection.get(&entrypoint.into()) {
75 let mut prepending_identifiers = element.uses();
76 while !prepending_identifiers.is_empty() {
77 prepending_identifiers
78 .iter()
79 .rev()
80 .for_each(|id| identifiers.push_front(id.clone()));
81
82 let mut new_identifiers = Vec::new();
83 for id in &prepending_identifiers {
84 if let Some(element) = collection.get(&id.into()) {
85 new_identifiers.extend(element.uses());
86 }
87 }
88
89 prepending_identifiers = new_identifiers;
90 }
91 }
92
93 identifiers.push_back(entrypoint.clone());
94
95 let elements = identifiers
96 .iter()
97 .unique()
98 .filter_map(|identifier| collection.get(&identifier.into()).map(|entry| entry.into()))
99 .collect();
100
101 Self { elements }
102 }
103}
104
105impl From<&CommonCollection> for Collection {
106 fn from(collection: &CommonCollection) -> Self {
107 Self {
108 elements: collection
109 .identifiers()
110 .iter()
111 .filter_map(|identifier| {
112 collection
113 .get(&(identifier.into()))
114 .map(|entry| entry.into())
115 })
116 .collect(),
117 }
118 }
119}