crossref/query/
types.rs

1use crate::error::{Error, ErrorKind, Result};
2use crate::query::works::{WorksCombiner, WorksFilter, WorksIdentQuery, WorksQuery};
3use crate::query::{Component, CrossrefQuery, CrossrefRoute, ResourceComponent};
4use serde::{Deserialize, Serialize};
5use std::str::FromStr;
6
7/// all possible types of a `Work`
8#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
9#[serde(tag = "id")]
10#[serde(rename_all = "kebab-case")]
11#[allow(missing_docs)]
12pub enum Type {
13    BookSection,
14    Monograph,
15    Report,
16    PeerReview,
17    BookTrack,
18    JournalArticle,
19    BookPart,
20    Other,
21    Book,
22    JournalVolume,
23    BookSet,
24    ReferenceEntry,
25    ProceedingsArticle,
26    Journal,
27    Component,
28    BookChapter,
29    ProceedingsSeries,
30    ReportSeries,
31    Proceedings,
32    Standard,
33    ReferenceBook,
34    PostedContent,
35    JournalIssue,
36    Dissertation,
37    Dataset,
38    BookSeries,
39    EditedBook,
40    StandardSeries,
41}
42
43impl Type {
44    /// the display-friendly label for the type
45    pub fn label(&self) -> &str {
46        match self {
47            Type::BookSection => "Book Section",
48            Type::Monograph => "Monograph",
49            Type::Report => "Report",
50            Type::PeerReview => "Peer Review",
51            Type::BookTrack => "Book Track",
52            Type::JournalArticle => "Journal Article",
53            Type::BookPart => "Book Part",
54            Type::Other => "Other",
55            Type::Book => "Book",
56            Type::JournalVolume => "Journal Volume",
57            Type::BookSet => "Book Set",
58            Type::ReferenceEntry => "Reference Entry",
59            Type::ProceedingsArticle => "Proceedings Article",
60            Type::Journal => "Journal",
61            Type::Component => "Component",
62            Type::BookChapter => "Book Chapter",
63            Type::ProceedingsSeries => "Proceedings Series",
64            Type::ReportSeries => "Report Series",
65            Type::Proceedings => "Proceedings",
66            Type::Standard => "Standard",
67            Type::ReferenceBook => "Reference Book",
68            Type::PostedContent => "Posted Content",
69            Type::JournalIssue => "Journal Issue",
70            Type::Dissertation => "Dissertation",
71            Type::Dataset => "Dataset",
72            Type::BookSeries => "Book Series",
73            Type::EditedBook => "Edited Book",
74            Type::StandardSeries => "Standard Series",
75        }
76    }
77    /// the string used to identify the type
78    pub fn id(&self) -> &str {
79        match self {
80            Type::BookSection => "book-section",
81            Type::Monograph => "monograph",
82            Type::Report => "report",
83            Type::PeerReview => "peer-review",
84            Type::BookTrack => "book-track",
85            Type::JournalArticle => "journal-article",
86            Type::BookPart => "book-part",
87            Type::Other => "other",
88            Type::Book => "book",
89            Type::JournalVolume => "journal-volume",
90            Type::BookSet => "book-set",
91            Type::ReferenceEntry => "reference-entry",
92            Type::ProceedingsArticle => "proceedings-article",
93            Type::Journal => "journal",
94            Type::Component => "component",
95            Type::BookChapter => "book-chapter",
96            Type::ProceedingsSeries => "proceedings-series",
97            Type::ReportSeries => "report-series",
98            Type::Proceedings => "proceedings",
99            Type::Standard => "standard",
100            Type::ReferenceBook => "reference-book",
101            Type::PostedContent => "posted-content",
102            Type::JournalIssue => "journal-issue",
103            Type::Dissertation => "dissertation",
104            Type::Dataset => "dataset",
105            Type::BookSeries => "book-series",
106            Type::EditedBook => "edited-book",
107            Type::StandardSeries => "standard-series",
108        }
109    }
110}
111
112impl FromStr for Type {
113    type Err = Error;
114
115    fn from_str(s: &str) -> Result<Self> {
116        match s {
117            "book-section" => Ok(Type::BookSection),
118            "monograph" => Ok(Type::Monograph),
119            "report" => Ok(Type::Report),
120            "peer-review" => Ok(Type::PeerReview),
121            "book-track" => Ok(Type::BookTrack),
122            "journal-article" => Ok(Type::JournalArticle),
123            "book-part" => Ok(Type::BookPart),
124            "other" => Ok(Type::Other),
125            "book" => Ok(Type::Book),
126            "journal-volume" => Ok(Type::JournalVolume),
127            "book-set" => Ok(Type::BookSet),
128            "reference-entry" => Ok(Type::ReferenceEntry),
129            "proceedings-article" => Ok(Type::ProceedingsArticle),
130            "journal" => Ok(Type::Journal),
131            "component" => Ok(Type::Component),
132            "book-chapter" => Ok(Type::BookChapter),
133            "proceedings-series" => Ok(Type::ProceedingsSeries),
134            "report-series" => Ok(Type::ReportSeries),
135            "proceedings" => Ok(Type::Proceedings),
136            "standard" => Ok(Type::Standard),
137            "reference-book" => Ok(Type::ReferenceBook),
138            "posted-content" => Ok(Type::PostedContent),
139            "journal-issue" => Ok(Type::JournalIssue),
140            "dissertation" => Ok(Type::Dissertation),
141            "dataset" => Ok(Type::Dataset),
142            "book-series" => Ok(Type::BookSeries),
143            "edited-book" => Ok(Type::EditedBook),
144            "standard-series" => Ok(Type::StandardSeries),
145            name => Err(Error::from(ErrorKind::InvalidTypeName {
146                name: name.to_string(),
147            })),
148        }
149    }
150}
151
152/// constructs the request payload for the `/types` route
153#[derive(Debug, Clone)]
154pub enum Types {
155    /// every available type
156    All,
157    /// target a specific type at `/types/{id}`
158    Identifier(String),
159    /// target a `Work` for a specific type at `/types/{id}/works?query..`
160    Works(WorksIdentQuery),
161}
162
163impl CrossrefRoute for Types {
164    fn route(&self) -> Result<String> {
165        match self {
166            Types::All => Component::Types.route(),
167            Types::Identifier(s) => Ok(format!("{}/{}", Component::Types.route()?, s)),
168            Types::Works(combined) => Self::combined_route(combined),
169        }
170    }
171}
172
173impl CrossrefQuery for Types {
174    fn resource_component(self) -> ResourceComponent {
175        ResourceComponent::Types(self)
176    }
177}
178
179#[cfg(test)]
180mod tests {
181    use super::*;
182    use serde_json::*;
183
184    //    #[test]
185    fn test_types() {
186        let section = r#"{
187    "id": "book-section",
188    "label": "Book Section"
189  }"#;
190        let ref_type: Type = serde_json::from_str(section).unwrap();
191
192        assert_eq!(Type::BookSection, ref_type);
193    }
194}