1#[macro_export]
10macro_rules! str_enum {
11 (
12 $(#[$meta:meta])*
13 $vis:vis enum $name:ident {
14 $(
15 $(#[$vmeta:meta])*
16 $variant:ident = $val:expr
17 ),+ $(,)?
18 }
19 ) => {
20 $(#[$meta])*
21 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
22 #[cfg_attr(feature = "bindings", derive(specta::Type))]
23 #[non_exhaustive]
24 $vis enum $name {
25 $(
26 $(#[$vmeta])*
27 #[cfg_attr(any(feature = "schema", feature = "bindings"), serde(rename = $val))]
28 $variant,
29 )+
30 #[doc = "Fallback for forward-compatibility."]
31 #[cfg_attr(feature = "schema", schemars(skip))]
32 #[cfg_attr(feature = "bindings", specta(skip))]
33 Unknown(String),
34 }
35
36 impl $name {
37 #[doc = "Returns the string value associated with this variant."]
38 #[must_use]
39 pub fn as_str(&self) -> &str {
40 match self {
41 $( Self::$variant => $val, )+
42 Self::Unknown(s) => s.as_str(),
43 }
44 }
45 }
46
47 impl serde::Serialize for $name {
48 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
49 where
50 S: serde::Serializer,
51 {
52 serializer.serialize_str(self.as_str())
53 }
54 }
55
56 impl<'de> serde::Deserialize<'de> for $name {
57 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58 where
59 D: serde::Deserializer<'de>,
60 {
61 struct Visitor;
62 impl<'de> serde::de::Visitor<'de> for Visitor {
63 type Value = $name;
64
65 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
66 formatter.write_str("a string")
67 }
68
69 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
70 where
71 E: serde::de::Error,
72 {
73 Ok(match value {
74 $( $val => $name::$variant, )+
75 _ => $name::Unknown(value.to_owned()),
76 })
77 }
78 }
79 deserializer.deserialize_str(Visitor)
80 }
81 }
82 }
83}
84
85#[macro_export]
89macro_rules! dispatch_component {
90 ($target:expr, |$inner:ident| $action:expr) => {
91 match $target {
92 $crate::template::TemplateComponent::Contributor($inner) => $action,
93 $crate::template::TemplateComponent::Date($inner) => $action,
94 $crate::template::TemplateComponent::Title($inner) => $action,
95 $crate::template::TemplateComponent::Number($inner) => $action,
96 $crate::template::TemplateComponent::Variable($inner) => $action,
97 $crate::template::TemplateComponent::Group($inner) => $action,
98 $crate::template::TemplateComponent::Term($inner) => $action,
99 }
100 };
101}
102
103#[macro_export]
106macro_rules! merge_options {
107 ($target:expr, $source:expr, $($field:ident),+ $(,)?) => {
108 $(
109 if $source.$field.is_some() {
110 $target.$field = $source.$field.clone();
111 }
112 )+
113 };
114}
115
116#[macro_export]
121macro_rules! tc_contributor {
122 ($role:ident, $form:ident $(, $key:ident = $val:expr)*) => {
123 $crate::template::TemplateComponent::Contributor(
124 $crate::template::TemplateContributor {
125 contributor: $crate::template::ContributorRole::$role,
126 form: $crate::template::ContributorForm::$form,
127 rendering: $crate::template::Rendering {
128 $( $key: Some($val.into()), )*
129 ..Default::default()
130 },
131 ..Default::default()
132 }
133 )
134 };
135}
136
137#[macro_export]
139macro_rules! tc_date {
140 ($date_var:ident, $form:ident $(, $key:ident = $val:expr)*) => {
141 $crate::template::TemplateComponent::Date(
142 $crate::template::TemplateDate {
143 date: $crate::template::DateVariable::$date_var,
144 form: $crate::template::DateForm::$form,
145 rendering: $crate::template::Rendering {
146 $( $key: Some($val.into()), )*
147 ..Default::default()
148 },
149 ..Default::default()
150 }
151 )
152 };
153}
154
155#[macro_export]
157macro_rules! tc_title {
158 ($title_type:ident $(, $key:ident = $val:expr)*) => {
159 $crate::template::TemplateComponent::Title(
160 $crate::template::TemplateTitle {
161 title: $crate::template::TitleType::$title_type,
162 rendering: $crate::template::Rendering {
163 $( $key: Some($val.into()), )*
164 ..Default::default()
165 },
166 ..Default::default()
167 }
168 )
169 };
170}
171
172#[macro_export]
174macro_rules! tc_number {
175 ($num_var:ident $(, $key:ident = $val:expr)*) => {
176 $crate::template::TemplateComponent::Number(
177 $crate::template::TemplateNumber {
178 number: $crate::template::NumberVariable::$num_var,
179 rendering: $crate::template::Rendering {
180 $( $key: Some($val.into()), )*
181 ..Default::default()
182 },
183 ..Default::default()
184 }
185 )
186 };
187}
188
189#[macro_export]
191macro_rules! tc_variable {
192 ($var:ident $(, $key:ident = $val:expr)*) => {
193 $crate::template::TemplateComponent::Variable(
194 $crate::template::TemplateVariable {
195 variable: $crate::template::SimpleVariable::$var,
196 rendering: $crate::template::Rendering {
197 $( $key: Some($val.into()), )*
198 ..Default::default()
199 },
200 ..Default::default()
201 }
202 )
203 };
204}
205
206#[macro_export]
208macro_rules! tc_term {
209 ($term_var:ident $(, $key:ident = $val:expr)*) => {
210 $crate::template::TemplateComponent::Term(
211 $crate::template::TemplateTerm {
212 term: $crate::locale::GeneralTerm::$term_var,
213 rendering: $crate::template::Rendering {
214 $( $key: Some($val.into()), )*
215 ..Default::default()
216 },
217 ..Default::default()
218 }
219 )
220 };
221}
222
223#[macro_export]
225macro_rules! tc_group {
226 ([$($item:expr),* $(,)?] $(, $key:ident = $val:expr)*) => {
227 $crate::template::TemplateComponent::Group(
228 $crate::template::TemplateGroup {
229 group: vec![$($item),*],
230 rendering: $crate::template::Rendering {
231 $( $key: Some($val.into()), )*
232 ..Default::default()
233 },
234 ..Default::default()
235 }
236 )
237 };
238}
239
240#[macro_export]
245macro_rules! ref_book {
246 ($id:expr, $family:expr, $given:expr, $year:expr, $title:expr) => {
247 $crate::reference::InputReference::Monograph(::std::boxed::Box::new(
248 $crate::reference::Monograph {
249 id: Some($id.into()),
250 r#type: $crate::reference::MonographType::Book,
251 title: Some($crate::reference::Title::Single($title.to_string())),
252 author: Some($crate::reference::Contributor::StructuredName(
253 $crate::reference::StructuredName {
254 family: $crate::reference::MultilingualString::Simple($family.to_string()),
255 given: $crate::reference::MultilingualString::Simple($given.to_string()),
256 ..Default::default()
257 },
258 )),
259 issued: $crate::reference::EdtfString($year.to_string()),
260 ..Default::default()
261 },
262 ))
263 };
264}
265
266#[macro_export]
268macro_rules! ref_book_authors {
269 ($id:expr, [$(($family:expr, $given:expr)),* $(,)?], $year:expr, $title:expr) => {{
270 let _authors: Vec<$crate::reference::Contributor> = vec![
271 $(
272 $crate::reference::Contributor::StructuredName(
273 $crate::reference::StructuredName {
274 family: $crate::reference::MultilingualString::Simple(
275 $family.to_string(),
276 ),
277 given: $crate::reference::MultilingualString::Simple($given.to_string()),
278 ..Default::default()
279 },
280 ),
281 )*
282 ];
283 $crate::reference::InputReference::Monograph(::std::boxed::Box::new(
284 $crate::reference::Monograph {
285 id: Some($id.into()),
286 r#type: $crate::reference::MonographType::Book,
287 title: Some($crate::reference::Title::Single($title.to_string())),
288 author: Some($crate::reference::Contributor::ContributorList(
289 $crate::reference::ContributorList(_authors),
290 )),
291 issued: $crate::reference::EdtfString($year.to_string()),
292 ..Default::default()
293 },
294 ))
295 }};
296}
297
298#[macro_export]
300macro_rules! ref_article {
301 ($id:expr, $family:expr, $given:expr, $year:expr, $title:expr) => {
302 $crate::reference::InputReference::SerialComponent(::std::boxed::Box::new(
303 $crate::reference::SerialComponent {
304 id: Some($id.into()),
305 r#type: $crate::reference::SerialComponentType::Article,
306 title: Some($crate::reference::Title::Single($title.to_string())),
307 author: Some($crate::reference::Contributor::StructuredName(
308 $crate::reference::StructuredName {
309 family: $crate::reference::MultilingualString::Simple($family.to_string()),
310 given: $crate::reference::MultilingualString::Simple($given.to_string()),
311 ..Default::default()
312 },
313 )),
314 issued: $crate::reference::EdtfString($year.to_string()),
315 container: Some($crate::reference::WorkRelation::Embedded(
316 ::std::boxed::Box::new($crate::reference::InputReference::Serial(
317 ::std::boxed::Box::new($crate::reference::Serial {
318 r#type: $crate::reference::SerialType::AcademicJournal,
319 title: Some($crate::reference::Title::Single(String::new())),
320 ..Default::default()
321 }),
322 )),
323 )),
324 ..Default::default()
325 },
326 ))
327 };
328}
329
330#[macro_export]
332macro_rules! ref_article_authors {
333 ($id:expr, [$(($family:expr, $given:expr)),* $(,)?], $year:expr, $title:expr) => {{
334 let _authors: Vec<$crate::reference::Contributor> = vec![
335 $(
336 $crate::reference::Contributor::StructuredName(
337 $crate::reference::StructuredName {
338 family: $crate::reference::MultilingualString::Simple(
339 $family.to_string(),
340 ),
341 given: $crate::reference::MultilingualString::Simple($given.to_string()),
342 ..Default::default()
343 },
344 ),
345 )*
346 ];
347 $crate::reference::InputReference::SerialComponent(::std::boxed::Box::new(
348 $crate::reference::SerialComponent {
349 id: Some($id.into()),
350 r#type: $crate::reference::SerialComponentType::Article,
351 title: Some($crate::reference::Title::Single($title.to_string())),
352 author: Some($crate::reference::Contributor::ContributorList(
353 $crate::reference::ContributorList(_authors),
354 )),
355 issued: $crate::reference::EdtfString($year.to_string()),
356 ..Default::default()
357 },
358 ))
359 }};
360}
361
362#[macro_export]
364macro_rules! citation_locator {
365 ($label:ident, $value:expr) => {
366 $crate::citation::CitationLocator::single(
367 $crate::citation::LocatorType::$label,
368 $value,
369 )
370 };
371 ($l1:ident => $v1:expr, $l2:ident => $v2:expr $(, $lrest:ident => $vrest:expr)* $(,)?) => {
372 $crate::citation::CitationLocator::compound(vec![
373 $crate::citation::LocatorSegment::new(
374 $crate::citation::LocatorType::$l1,
375 $v1,
376 ),
377 $crate::citation::LocatorSegment::new(
378 $crate::citation::LocatorType::$l2,
379 $v2,
380 ),
381 $(
382 $crate::citation::LocatorSegment::new(
383 $crate::citation::LocatorType::$lrest,
384 $vrest,
385 )
386 ),*
387 ]).expect("compound locator macro requires at least two segments")
388 };
389}
390
391#[macro_export]
393macro_rules! citation_item {
394 ($id:expr $(, $key:ident = $val:expr)*) => {{
395 #[allow(unused_mut)]
396 let mut _item = $crate::citation::CitationItem {
397 id: $id.to_string(),
398 ..Default::default()
399 };
400 $( citation_item!(@set _item, $key, $val); )*
401 _item
402 }};
403 (@set $item:ident, locator, $val:expr) => { $item.locator = Some($val); };
404 (@set $item:ident, prefix, $val:expr) => { $item.prefix = Some($val.to_string()); };
405 (@set $item:ident, suffix, $val:expr) => { $item.suffix = Some($val.to_string()); };
406}
407
408#[macro_export]
410macro_rules! citation {
411 ([$($item:expr),* $(,)?] $(, $key:ident = $val:expr)* $(,)?) => {
412 $crate::citation::Citation {
413 items: vec![$($item),*],
414 $($key: $val,)*
415 ..Default::default()
416 }
417 };
418}
419
420#[macro_export]
422macro_rules! cite {
423 ($id:expr) => {
424 $crate::citation::Citation {
425 items: vec![$crate::citation::CitationItem {
426 id: $id.to_string(),
427 ..Default::default()
428 }],
429 ..Default::default()
430 }
431 };
432 ($id:expr, $key:ident = $val:expr) => {
433 $crate::citation::Citation {
434 items: vec![$crate::citation::CitationItem {
435 id: $id.to_string(),
436 ..Default::default()
437 }],
438 $key: $val,
439 ..Default::default()
440 }
441 };
442}
443
444#[macro_export]
446macro_rules! bib_map {
447 ($($key:expr => $val:expr),* $(,)?) => {{
448 #[allow(unused_mut)]
449 let mut _map = indexmap::IndexMap::new();
450 $( _map.insert($key.to_string(), $val); )*
451 _map
452 }};
453}