1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::query::{CrossrefQueryParam, ParamFragment};
use std::borrow::Cow;
/// all available facets that can be set as filter in a query
#[derive(Debug, Clone)]
pub enum Facet {
/// Author affiliation
Affiliation,
/// Funder literal name as deposited alongside DOIs
FunderName,
/// Funder DOI
FunderDoi,
/// Contributor ORCID
ORCID,
/// Work container title, such as journal title, or book title
ContainerTitle,
/// Custom Crossmark assertion name
Assertion,
/// Archive location
Archive,
/// Significant update type
UpdateType,
/// Journal ISSN (any - print, electronic, link)
ISSN,
/// Earliest year of publication
Published,
/// Work type name, such as `journal-article` or `book-chapter`
TypeName,
/// License URI of work
License,
/// Category name of work
CategoryName,
/// Relation type described by work or described by another work with work as object
RelationType,
/// Custom Crossmark assertion group name
AssertionGroup,
/// Publisher name of work
PublisherName,
}
impl Facet {
/// the maximum numeric number some facets are not allowed to exceed
pub const MAX_VAL_NUM: usize = 100;
/// the maximum value the facets can hold
/// some facets are unbounded `*`, some are limited to [MAX_VAL_NUM]
fn max_value(&self) -> &str {
match self {
Facet::ORCID | Facet::ContainerTitle | Facet::ISSN => "100",
_ => "*",
}
}
/// the key name for the query fragment
fn as_str(&self) -> &str {
match self {
Facet::Affiliation => "affiliation",
Facet::FunderName => "funder-name",
Facet::FunderDoi => "funder-doi",
Facet::ORCID => "orcid",
Facet::ContainerTitle => "container-title",
Facet::Assertion => "assertion",
Facet::Archive => "archive",
Facet::UpdateType => "update-type",
Facet::ISSN => "issn",
Facet::Published => "published",
Facet::TypeName => "type-name",
Facet::License => "license",
Facet::CategoryName => "category-name",
Facet::RelationType => "relation-type",
Facet::AssertionGroup => "assertion-group",
Facet::PublisherName => "publisher-name",
}
}
}
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub struct FacetCount {
/// the targeted facet
pub facet: Facet,
/// the maximum number
pub count: Option<usize>,
}
impl FacetCount {
fn value(&self) -> String {
match &self.count {
Some(count) => match self.facet {
Facet::ORCID | Facet::ContainerTitle | Facet::ISSN => {
if *count > Facet::MAX_VAL_NUM {
Facet::MAX_VAL_NUM.to_string()
} else {
count.to_string()
}
}
_ => count.to_string(),
},
_ => self.facet.max_value().to_string(),
}
}
}
impl ParamFragment for FacetCount {
fn key(&self) -> Cow<str> {
Cow::Borrowed(self.facet.as_str())
}
fn value(&self) -> Option<Cow<str>> {
Some(Cow::Owned(self.value()))
}
}
impl CrossrefQueryParam for Vec<FacetCount> {
fn param_key(&self) -> Cow<str> {
Cow::Borrowed("facet")
}
fn param_value(&self) -> Option<Cow<str>> {
Some(Cow::Owned(
self.iter()
.map(ParamFragment::fragment)
.collect::<Vec<_>>()
.join(","),
))
}
}