rustronomy_core/meta/custom/
reference_pub.rs

1/*
2  Copyright© 2023 Raúl Wolters(1)
3
4  This file is part of rustronomy-core.
5
6  rustronomy is free software: you can redistribute it and/or modify it under
7  the terms of the European Union Public License version 1.2 or later, as
8  published by the European Commission.
9
10  rustronomy is distributed in the hope that it will be useful, but WITHOUT ANY
11  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12  A PARTICULAR PURPOSE. See the European Union Public License for more details.
13
14  You should have received a copy of the EUPL in an/all official language(s) of
15  the European Union along with rustronomy.  If not, see
16  <https://ec.europa.eu/info/european-union-public-licence_en/>.
17
18  (1) Resident of the Kingdom of the Netherlands; agreement between licensor and
19  licensee subject to Dutch law as per article 15 of the EUPL.
20*/
21
22use crate::meta::MetaTag;
23use chrono::Datelike;
24
25use getset::{Getters, Setters, MutGetters};
26
27#[derive(Debug, Clone, PartialEq, Default, Getters, Setters, MutGetters)]
28#[getset(get = "pub", set = "pub", get_mut = "pub")]
29/// Struct representing a reference to an (academic) publication describing the
30/// data inside the container. To be used as a rustronomy `MetaTag`.
31/// 
32/// # Optional fields
33/// This struct contains a lot of optional data which may be accessed using the
34/// `self.xyz()`, `self.xyz_mut()` and `self.set_xyz()` methods. Currently,
35/// the following optional metadata is supported (more may be added in the future):
36/// - `affiliation` affiliation of the authors
37/// - `journal`, `number`, `volume`, `pages` to direct users to the publication 
38/// - `doi` [Digital Object Identifier](https://www.doi.org/)
39/// - `url` url to publication (e.g. arXiv or publisher site)
40/// - `date` date of publishing
41/// - `email` contact info for author handling correspondence
42/// 
43/// *Note: these struct fields have to be private because changing the number of
44/// public struct fields is currently a breaking change in Rust. This is why getters
45/// and setters are used here.*
46pub struct ReferencePublication {
47  title: String,
48  authors: String,
49  affiliation: Option<String>,
50
51  journal: Option<String>,
52  number: Option<u16>,
53  volume: Option<u16>,
54  pages: Option<(u16, u16)>,
55  doi: Option<String>,
56  url: Option<String>,
57  date: Option<chrono::NaiveDate>,
58
59  email: Option<String>,
60}
61
62impl ReferencePublication {
63  /// Constructs a `ReferencePublication` with all optional fields set to `None`
64  pub fn new(title: &str, authors: &str) -> Self {
65    let mut out = ReferencePublication::default();
66    out.title = title.to_string();
67    out.authors = authors.to_string();
68    out
69  }
70}
71
72impl MetaTag for ReferencePublication {}
73impl std::fmt::Display for ReferencePublication {
74  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75    writeln!(f, "[Reference Publication]: ")?;
76    writeln!(f, "    \"{}\"", self.title)?;
77    write!(f, "    Authors: {}", self.authors)?;
78    if let Some(af) = &self.affiliation {
79      write!(f, "\n    Affiliation: {af}")?
80    };
81    if let Some(journal) = &self.journal {
82      write!(f, "\n    In \"{journal}\", ")?
83    };
84    if let Some(volume) = self.volume {
85      write!(f, "Vol.{volume}, ")?
86    };
87    if let Some(number) = self.number {
88      write!(f, "№{number} ")?
89    };
90    if let Some((p1, p2)) = self.pages {
91      write!(f, "pages {p1}-{p2} ")?
92    };
93    if let Some(date) = self.date {
94      write!(f, "({})", date.year())?
95    };
96    if let Some(url) = &self.url {
97      write!(f, "\n    URL: {url}")?
98    };
99    if let Some(doi) = &self.doi {
100      write!(f, "\n    DOI: {doi}")?
101    };
102    if let Some(email) = &self.email {
103      write!(f, "\n    Contact: {email}")?
104    };
105    Ok(())
106  }
107}