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}