gedcomx/
macros.rs

1macro_rules! try_from_evidencereference {
2    ($from_type: ty) => {
3        impl TryFrom<&$from_type> for crate::EvidenceReference {
4            type Error = GedcomxError;
5
6            fn try_from(f: &$from_type) -> Result<Self, Self::Error> {
7                match &f.id {
8                    Some(id) => Ok(Self::new(id.into(), None)),
9                    None => Err(GedcomxError::no_id_error(f)),
10                }
11            }
12        }
13    };
14}
15
16macro_rules! impl_enumasstring_yaserialize_yadeserialize {
17    ($for_type: ty, $name: tt) => {
18        impl yaserde::YaSerialize for $for_type {
19            fn serialize<W: std::io::Write>(
20                &self,
21                writer: &mut yaserde::ser::Serializer<W>,
22            ) -> std::result::Result<(), String> {
23                let _ret = writer.write(xml::writer::XmlEvent::characters(&self.to_string()));
24                Ok(())
25            }
26
27            fn serialize_attributes(
28                &self,
29                attributes: Vec<xml::attribute::OwnedAttribute>,
30                namespace: xml::namespace::Namespace,
31            ) -> std::result::Result<
32                (
33                    Vec<xml::attribute::OwnedAttribute>,
34                    xml::namespace::Namespace,
35                ),
36                String,
37            > {
38                Ok((attributes, namespace))
39            }
40        }
41
42        impl yaserde::YaDeserialize for $for_type {
43            fn deserialize<R: std::io::Read>(
44                reader: &mut yaserde::de::Deserializer<R>,
45            ) -> std::result::Result<Self, String> {
46                if let xml::reader::XmlEvent::StartElement { name, .. } = reader.peek()?.to_owned()
47                {
48                    let expected_name = $name.to_owned();
49                    if name.local_name != expected_name {
50                        return Err(format!(
51                            "Wrong StartElement name: {}, expected: {}",
52                            name, expected_name
53                        ));
54                    }
55                    let _next = reader.next_event();
56                } else {
57                    return Err("StartElement missing".to_string());
58                }
59
60                if let xml::reader::XmlEvent::Characters(text) = reader.peek()?.to_owned() {
61                    let enum_as_string = crate::EnumAsString(text);
62                    Ok(Self::from(enum_as_string))
63                } else {
64                    Err("Characters missing".to_string())
65                }
66            }
67        }
68    };
69}
70
71macro_rules! impl_characters_yaserialize_yadeserialize {
72    ($for_type: ty, $name: tt) => {
73        impl yaserde::YaSerialize for $for_type {
74            fn serialize<W: std::io::Write>(
75                &self,
76                writer: &mut yaserde::ser::Serializer<W>,
77            ) -> Result<(), String> {
78                let _ret = writer.write(xml::writer::XmlEvent::characters(&self.0));
79                Ok(())
80            }
81
82            fn serialize_attributes(
83                &self,
84                attributes: Vec<xml::attribute::OwnedAttribute>,
85                namespace: xml::namespace::Namespace,
86            ) -> Result<
87                (
88                    Vec<xml::attribute::OwnedAttribute>,
89                    xml::namespace::Namespace,
90                ),
91                String,
92            > {
93                Ok((attributes, namespace))
94            }
95        }
96
97        impl yaserde::YaDeserialize for $for_type {
98            fn deserialize<R: std::io::Read>(
99                reader: &mut yaserde::de::Deserializer<R>,
100            ) -> Result<Self, String> {
101                if let xml::reader::XmlEvent::StartElement { name, .. } = reader.peek()?.to_owned()
102                {
103                    let expected_name = $name.to_owned();
104                    if name.local_name != expected_name {
105                        return Err(format!(
106                            "Wrong StartElement name: {}, expected: {}",
107                            name, expected_name
108                        ));
109                    }
110                    let _next = reader.next_event();
111                } else {
112                    return Err("StartElement missing".to_string());
113                }
114
115                if let xml::reader::XmlEvent::Characters(text) = reader.peek()?.to_owned() {
116                    Ok(Self(text))
117                } else {
118                    Err("Characters missing".to_string())
119                }
120            }
121        }
122    };
123}
124
125macro_rules! conclusion_builder_functions {
126    ($final_type: ty) => {
127        pub fn id<I: Into<crate::Id>>(&mut self, id: I) -> &mut Self {
128            self.0.id = Some(id.into());
129            self
130        }
131
132        pub fn lang<I: Into<crate::Lang>>(&mut self, lang: I) -> &mut Self {
133            self.0.lang = Some(lang.into());
134            self
135        }
136
137        /// # Errors
138        ///
139        /// Will return [`GedcomxError::NoId`](crate::GedcomxError::NoId) if a
140        /// conversion into [`SourceReference`](crate::SourceReference) fails.
141        /// This happens if `source` has no `id` set.
142        pub fn source<
143            I: std::convert::TryInto<crate::SourceReference, Error = crate::GedcomxError>,
144        >(
145            &mut self,
146            source: I,
147        ) -> crate::Result<&mut Self> {
148            self.0.sources.push(source.try_into()?);
149            Ok(self)
150        }
151
152        pub fn source_ref(&mut self, source_ref: crate::SourceReference) -> &mut Self {
153            self.0.sources.push(source_ref);
154            self
155        }
156
157        /// # Errors
158        ///
159        /// Will return [`GedcomxError`](crate::GedcomxError) if a conversion into
160        /// [`Document`](crate::Document) fails. This happens if `document` has no `id`
161        /// set or has the wrong `document_type`.
162        pub fn analysis(&mut self, document: &crate::Document) -> crate::Result<&mut Self> {
163            use std::convert::TryInto;
164            self.0.analysis = Some(document.try_into()?);
165            Ok(self)
166        }
167
168        pub fn note(&mut self, note: crate::Note) -> &mut Self {
169            self.0.notes.push(note);
170            self
171        }
172
173        pub fn confidence(&mut self, confidence: crate::ConfidenceLevel) -> &mut Self {
174            self.0.confidence = Some(confidence);
175            self
176        }
177
178        pub fn attribution(&mut self, attribution: crate::Attribution) -> &mut Self {
179            self.0.attribution = Some(attribution);
180            self
181        }
182    };
183}
184
185macro_rules! subject_builder_functions {
186    ($final_type: ty) => {
187        conclusion_builder_functions!($final_type);
188
189        pub fn extracted(&mut self, extracted: bool) -> &mut Self {
190            self.0.extracted = Some(extracted);
191            self
192        }
193
194        /// # Errors
195        ///
196        /// Will return [`GedcomxError::NoId`](crate::GedcomxError::NoId) if a
197        /// conversion into [`EvidenceReference`](crate::EvidenceReference) fails.
198        /// This happens if the passed argument has no `id` set.
199        pub fn evidence(&mut self, e: &$final_type) -> crate::Result<&mut Self> {
200            use std::convert::TryInto;
201            self.0.evidence.push(e.try_into()?);
202            Ok(self)
203        }
204
205        /// # Errors
206        ///
207        /// Will return [`GedcomxError::NoId`](crate::GedcomxError::NoId) if a
208        /// conversion into [`SourceReference`](crate::SourceReference) fails.
209        /// This happens if `media` has no `id` set.
210        pub fn media(&mut self, media: &crate::SourceDescription) -> crate::Result<&mut Self> {
211            use std::convert::TryInto;
212            self.0.media.push(media.try_into()?);
213            Ok(self)
214        }
215
216        pub fn identifier(&mut self, identifier: crate::Identifier) -> &mut Self {
217            self.0.identifiers.push(identifier);
218            self
219        }
220    };
221}
222
223// From https://github.com/time-rs/time/blob/9021a7c7017dd094c1a7b2f61310e7d236d94341/src/quickcheck.rs
224macro_rules! arbitrary_between {
225    ($type:ty; $gen:expr, $min:expr, $max:expr) => {{
226        let min = $min;
227        let max = $max;
228        let range = max - min;
229        <$type>::arbitrary($gen).rem_euclid(range + 1) + min
230    }};
231}