1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::ops::Range;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7pub enum Argument {
8 Positioned { position: usize, value: Value },
10 Named { key: String, value: Value },
12}
13
14#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
16pub enum Value {
17 String(String),
18 Number(f64),
19 Boolean(bool),
20 List(Vec<Value>),
21 Map(HashMap<String, Value>),
22 Reference(String), DataSourceReference(String), }
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28pub struct ArgumentList {
29 pub arguments: Vec<Argument>,
30}
31
32impl ArgumentList {
33 pub fn new(arguments: Vec<Argument>) -> Self {
34 Self { arguments }
35 }
36
37 pub fn empty() -> Self {
38 Self { arguments: vec![] }
39 }
40
41 pub fn as_map(&self) -> HashMap<String, Value> {
42 self.arguments
43 .iter()
44 .enumerate()
45 .map(|(i, arg)| match arg {
46 Argument::Positioned { value, .. } => (i.to_string(), value.clone()),
47 Argument::Named { key, value } => (key.clone(), value.clone()),
48 })
49 .collect()
50 }
51
52 pub fn get_named(&self, key: &str) -> Option<&Value> {
53 self.arguments.iter().find_map(|arg| match arg {
54 Argument::Named { key: k, value } if k == key => Some(value),
55 _ => None,
56 })
57 }
58
59 pub fn get_positioned(&self, position: usize) -> Option<&Value> {
60 self.arguments.iter().find_map(|arg| match arg {
61 Argument::Positioned { position: p, value } if *p == position => Some(value),
62 _ => None,
63 })
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
69pub struct MetaData {
70 pub internal_id: String,
71 pub name_range: Range<usize>,
72 pub block_range: Option<Range<usize>>,
73}
74
75#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77pub struct ApplicatorSpecification {
78 pub name: String,
79 pub arguments: ArgumentList,
80 pub children: Vec<ComponentSpecification>,
81 pub internal_id: String,
82}
83
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
86pub enum DeclarationType {
87 Component,
89 Module,
91 ComponentKeyword,
93}
94
95#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
97pub struct ComponentSpecification {
98 pub id: String,
99 pub name: String,
100 pub declaration_type: DeclarationType,
101 pub arguments: ArgumentList,
102 pub applicators: Vec<ApplicatorSpecification>,
103 pub children: Vec<ComponentSpecification>,
104 pub metadata: MetaData,
105}
106
107impl ComponentSpecification {
108 pub fn new(
109 id: String,
110 name: String,
111 arguments: ArgumentList,
112 applicators: Vec<ApplicatorSpecification>,
113 children: Vec<ComponentSpecification>,
114 metadata: MetaData,
115 ) -> Self {
116 Self {
117 id,
118 name,
119 declaration_type: DeclarationType::Component,
120 arguments,
121 applicators,
122 children,
123 metadata,
124 }
125 }
126
127 pub fn with_declaration_type(mut self, declaration_type: DeclarationType) -> Self {
128 self.declaration_type = declaration_type;
129 self
130 }
131
132 pub fn flatten(&self) -> Vec<ComponentSpecification> {
134 let mut result = vec![self.clone()];
135 for child in &self.children {
136 result.extend(child.flatten());
137 }
138 result
139 }
140
141 pub fn to_applicator(&self) -> ApplicatorSpecification {
143 ApplicatorSpecification {
144 name: self.name.trim_start_matches('.').to_string(),
145 arguments: self.arguments.clone(),
146 children: self.children.clone(),
147 internal_id: self.metadata.internal_id.clone(),
148 }
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
154pub enum ImportClause {
155 Named(Vec<String>),
157 Default(String),
159}
160
161#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
163pub enum ImportSource {
164 Local(String),
166 Url(String),
168}
169
170#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
172pub struct ImportStatement {
173 pub clause: ImportClause,
175 pub source: ImportSource,
177}
178
179impl ImportStatement {
180 pub fn new(clause: ImportClause, source: ImportSource) -> Self {
181 Self { clause, source }
182 }
183
184 pub fn source_path(&self) -> &str {
186 match &self.source {
187 ImportSource::Local(path) => path,
188 ImportSource::Url(url) => url,
189 }
190 }
191
192 pub fn imported_names(&self) -> Vec<String> {
194 match &self.clause {
195 ImportClause::Named(names) => names.clone(),
196 ImportClause::Default(name) => vec![name.clone()],
197 }
198 }
199}
200
201#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
203pub struct Document {
204 pub imports: Vec<ImportStatement>,
206 pub components: Vec<ComponentSpecification>,
208}
209
210impl Document {
211 pub fn new(imports: Vec<ImportStatement>, components: Vec<ComponentSpecification>) -> Self {
212 Self {
213 imports,
214 components,
215 }
216 }
217
218 pub fn empty() -> Self {
219 Self {
220 imports: vec![],
221 components: vec![],
222 }
223 }
224}