egml_core/model/base/
abstract_gml.rs1use crate::model::abstract_object::{AbstractObject, AsAbstractObject, AsAbstractObjectMut};
2use crate::model::base::Id;
3use crate::model::basic_types::Code;
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
11pub struct AbstractGml {
12 pub abstract_object: AbstractObject,
13 id: Option<Id>,
15 names: Box<[Code]>,
20}
21
22impl AbstractGml {
23 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn from_abstract_object(abstract_object: AbstractObject) -> Self {
40 Self {
41 abstract_object,
42 id: None,
43 names: Box::default(),
44 }
45 }
46
47 pub fn with_id(id: Id) -> Self {
60 Self {
61 id: Some(id),
62 ..Default::default()
63 }
64 }
65
66 pub fn with_optional_id(id: Option<Id>) -> Self {
71 Self {
72 id,
73 ..Default::default()
74 }
75 }
76}
77
78pub trait AsAbstractGml: AsAbstractObject {
84 fn abstract_gml(&self) -> &AbstractGml;
86
87 fn id(&self) -> Option<&Id> {
89 self.abstract_gml().id.as_ref()
90 }
91
92 fn names(&self) -> &[Code] {
94 &self.abstract_gml().names
95 }
96}
97
98pub trait AsAbstractGmlMut: AsAbstractObjectMut + AsAbstractGml {
103 fn abstract_gml_mut(&mut self) -> &mut AbstractGml;
105
106 fn set_id(&mut self, id: Id) {
108 self.abstract_gml_mut().id = Some(id);
109 }
110
111 fn set_id_opt(&mut self, id: Option<Id>) {
113 self.abstract_gml_mut().id = id;
114 }
115
116 fn clear_id(&mut self) {
118 self.abstract_gml_mut().id = None;
119 }
120
121 fn set_names(&mut self, names: Vec<Code>) {
122 self.abstract_gml_mut().names = names.into_boxed_slice();
123 }
124
125 fn push_name(&mut self, name: Code) {
127 self.extend_names([name]);
128 }
129
130 fn extend_names(&mut self, names: impl IntoIterator<Item = Code>) {
132 let current = std::mem::take(&mut self.abstract_gml_mut().names);
133 self.abstract_gml_mut().names = current.into_vec().into_iter().chain(names).collect();
134 }
135}
136
137impl AsAbstractGml for AbstractGml {
138 fn abstract_gml(&self) -> &AbstractGml {
139 self
140 }
141}
142
143impl AsAbstractGmlMut for AbstractGml {
144 fn abstract_gml_mut(&mut self) -> &mut AbstractGml {
145 self
146 }
147}
148
149#[macro_export]
150macro_rules! impl_abstract_gml_traits {
151 ($type:ty) => {
152 impl $crate::model::AsAbstractObject for $type {
153 fn abstract_object(&self) -> &$crate::model::AbstractObject {
154 &<$type as $crate::model::base::AsAbstractGml>::abstract_gml(self).abstract_object
155 }
156 }
157 };
158}
159
160#[macro_export]
161macro_rules! impl_abstract_gml_mut_traits {
162 ($type:ty) => {
163 impl $crate::model::AsAbstractObjectMut for $type {
164 fn abstract_object_mut(&mut self) -> &mut $crate::model::AbstractObject {
165 &mut <$type as $crate::model::base::AsAbstractGmlMut>::abstract_gml_mut(self)
166 .abstract_object
167 }
168 }
169 };
170}
171
172impl_abstract_gml_traits!(AbstractGml);
173impl_abstract_gml_mut_traits!(AbstractGml);
174
175#[cfg(test)]
176mod tests {
177 use super::{AbstractGml, AsAbstractGml, AsAbstractGmlMut};
178 use crate::model::basic_types::Code;
179
180 #[test]
181 fn push_name_appends_in_order() {
182 let mut gml = AbstractGml::new();
183 gml.push_name("a".into());
184 gml.push_name("b".into());
185 assert_eq!(gml.names(), [Code::from("a"), Code::from("b")]);
186 }
187
188 #[test]
189 fn extend_names_keeps_existing_names() {
190 let mut gml = AbstractGml::new();
191 gml.set_names(vec!["a".into()]);
192 gml.extend_names(["b".into(), "c".into()]);
193 assert_eq!(
194 gml.names(),
195 [Code::from("a"), Code::from("b"), Code::from("c")]
196 );
197 }
198}