microcad_lang/model/attribute/
mod.rs1mod attributes;
7mod export_command;
8mod layer;
9mod measure_command;
10mod resolution_attribute;
11
12pub use attributes::Attributes;
13pub use export_command::ExportCommand;
14pub use layer::Layer;
15pub use measure_command::MeasureCommand;
16pub use resolution_attribute::ResolutionAttribute;
17
18use crate::{syntax::*, value::*};
19
20use microcad_core::{Color, Size2};
21
22#[derive(Clone, Debug)]
24pub struct CustomCommand {
25 pub id: Identifier,
27 pub arguments: Box<Tuple>,
29}
30
31impl std::fmt::Display for CustomCommand {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "{} = {}", self.id, self.arguments)
34 }
35}
36
37#[derive(Clone, Debug)]
39pub enum Attribute {
40 Color(Color),
42 Resolution(ResolutionAttribute),
44 Size(Size2),
46 Export(ExportCommand),
48 Measure(MeasureCommand),
50 Custom(CustomCommand),
52}
53
54impl Attribute {
55 fn id(&self) -> Identifier {
57 match &self {
58 Attribute::Color(_) => Identifier::no_ref("color"),
59 Attribute::Resolution(_) => Identifier::no_ref("resolution"),
60 Attribute::Size(_) => Identifier::no_ref("size"),
61 Attribute::Export(_) => Identifier::no_ref("export"),
62 Attribute::Measure(_) => Identifier::no_ref("measure"),
63 Attribute::Custom(attr) => attr.id.clone(),
64 }
65 }
66
67 pub fn is_unique(&self) -> bool {
69 matches!(
70 self,
71 Attribute::Color(_) | Attribute::Resolution(_) | Attribute::Size(_)
72 )
73 }
74}
75
76impl std::fmt::Display for Attribute {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 write!(
79 f,
80 "#[{id} = {value}]",
81 id = self.id(),
82 value = match &self {
83 Attribute::Color(color) => format!("{color}"),
84 Attribute::Resolution(resolution) => format!("{resolution}"),
85 Attribute::Size(size) => format!("{size}"),
86 Attribute::Export(export) => format!("{export}"),
87 Attribute::Measure(measure) => format!("{measure}"),
88 Attribute::Custom(command) => format!("{command}"),
89 }
90 )
91 }
92}
93
94impl From<Attribute> for Value {
96 fn from(value: Attribute) -> Self {
97 match value {
98 Attribute::Color(color) => Value::Tuple(Box::new(color.into())),
99 Attribute::Resolution(resolution_attribute) => resolution_attribute.into(),
100 Attribute::Size(size) => size.into(),
101 Attribute::Export(e) => e.into(),
102 Attribute::Measure(m) => m.into(),
103 Attribute::Custom(attr) => Value::Tuple(attr.arguments.clone()),
104 }
105 }
106}
107
108impl PartialEq for Attribute {
109 fn eq(&self, other: &Self) -> bool {
110 self.id() == other.id()
111 }
112}
113
114pub trait AttributesAccess {
116 fn get_attributes_by_id(&self, id: &Identifier) -> Vec<Attribute>;
118
119 fn get_single_attribute(&self, id: &Identifier) -> Option<Attribute> {
121 let attributes = self.get_attributes_by_id(id);
122 match attributes.len() {
123 1 => attributes.first().cloned(),
124 _ => None,
125 }
126 }
127
128 fn get_attribute_value(&self, id: &Identifier) -> Value {
130 match self.get_single_attribute(id) {
131 Some(attribute) => attribute.into(),
132 None => Value::None,
133 }
134 }
135
136 fn get_resolution(&self) -> Option<ResolutionAttribute> {
138 match self.get_single_attribute(&Identifier::no_ref("resolution")) {
139 Some(value) => match value {
140 Attribute::Resolution(resolution) => Some(resolution),
141 _ => unreachable!(),
142 },
143 None => None,
144 }
145 }
146
147 fn get_color(&self) -> Option<Color> {
149 match self.get_single_attribute(&Identifier::no_ref("color")) {
150 Some(value) => match value {
151 Attribute::Color(color) => Some(color),
152 _ => unreachable!(),
153 },
154 None => None,
155 }
156 }
157
158 fn get_size(&self) -> Option<Size2> {
160 self.get_single_attribute(&Identifier::no_ref("size"))
161 .map(|attr| match attr {
162 Attribute::Size(size) => size,
163 _ => unreachable!(),
164 })
165 }
166
167 fn get_exports(&self) -> Vec<ExportCommand> {
169 self.get_attributes_by_id(&Identifier::no_ref("export"))
170 .into_iter()
171 .fold(Vec::new(), |mut exports, command| {
172 match command {
173 Attribute::Export(export_command) => exports.push(export_command.clone()),
174 _ => unreachable!(),
175 }
176 exports
177 })
178 }
179
180 fn get_measures(&self) -> Vec<MeasureCommand> {
182 self.get_attributes_by_id(&Identifier::no_ref("measure"))
183 .iter()
184 .fold(Vec::new(), |mut measures, attribute| {
185 match attribute {
186 Attribute::Measure(measure_command) => measures.push(measure_command.clone()),
187 _ => unreachable!(),
188 }
189 measures
190 })
191 }
192
193 fn get_custom_attributes(&self, id: &Identifier) -> Vec<Tuple> {
195 self.get_attributes_by_id(id)
196 .iter()
197 .fold(Vec::new(), |mut attributes, attribute| {
198 match attribute {
199 Attribute::Custom(attr) => attributes.push(attr.arguments.as_ref().clone()),
200 _ => unreachable!(),
201 }
202 attributes
203 })
204 }
205}