1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub struct Paper {
8 #[serde(default)]
9 pub paper_id: String,
10 #[serde(default)]
11 pub corpus_id: Option<u64>,
12 #[serde(default)]
13 pub external_ids: Option<ExternalIds>,
14 #[serde(default)]
15 pub url: Option<String>,
16 #[serde(default)]
17 pub title: Option<String>,
18 #[serde(default, rename = "abstract")]
19 pub abstract_text: Option<String>,
20 #[serde(default)]
21 pub venue: Option<String>,
22 #[serde(default)]
23 pub publication_venue: Option<PublicationVenue>,
24 #[serde(default)]
25 pub year: Option<u32>,
26 #[serde(default)]
27 pub reference_count: Option<u32>,
28 #[serde(default)]
29 pub citation_count: Option<u32>,
30 #[serde(default)]
31 pub influential_citation_count: Option<u32>,
32 #[serde(default)]
33 pub is_open_access: Option<bool>,
34 #[serde(default)]
35 pub open_access_pdf: Option<OpenAccessPdf>,
36 #[serde(default)]
37 pub fields_of_study: Option<Vec<String>>,
38 #[serde(default)]
39 pub s2_fields_of_study: Option<Vec<S2FieldOfStudy>>,
40 #[serde(default)]
41 pub publication_types: Option<Vec<String>>,
42 #[serde(default)]
43 pub publication_date: Option<String>,
44 #[serde(default)]
45 pub journal: Option<Journal>,
46 #[serde(default)]
47 pub citation_styles: Option<CitationStyles>,
48 #[serde(default)]
49 pub authors: Option<Vec<AuthorRef>>,
50 #[serde(default)]
51 pub citations: Option<Vec<Citation>>,
52 #[serde(default)]
53 pub references: Option<Vec<Reference>>,
54 #[serde(default)]
55 pub tldr: Option<Tldr>,
56}
57
58impl fmt::Display for Paper {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 let title = self.title.as_deref().unwrap_or("(untitled)");
61 write!(f, "{title}")?;
62 if let Some(year) = self.year {
63 write!(f, " ({year})")?;
64 }
65 if let Some(authors) = &self.authors {
66 let names: Vec<&str> = authors
67 .iter()
68 .filter_map(|a| a.name.as_deref())
69 .take(3)
70 .collect();
71 if !names.is_empty() {
72 write!(f, " — {}", names.join(", "))?;
73 if authors.len() > 3 {
74 write!(f, " et al.")?;
75 }
76 }
77 }
78 Ok(())
79 }
80}
81
82#[derive(Debug, Clone, Default, Serialize, Deserialize)]
84pub struct ExternalIds {
85 #[serde(default, rename = "DOI")]
86 pub doi: Option<String>,
87 #[serde(default, rename = "ArXiv")]
88 pub arxiv: Option<String>,
89 #[serde(default, rename = "MAG")]
90 pub mag: Option<String>,
91 #[serde(default, rename = "ACL")]
92 pub acl: Option<String>,
93 #[serde(default, rename = "PubMed")]
94 pub pubmed: Option<String>,
95 #[serde(default, rename = "PubMedCentral")]
96 pub pubmed_central: Option<String>,
97 #[serde(default, rename = "DBLP")]
98 pub dblp: Option<String>,
99 #[serde(default, rename = "CorpusId")]
100 pub corpus_id: Option<u64>,
101}
102
103#[derive(Debug, Clone, Default, Serialize, Deserialize)]
104pub struct PublicationVenue {
105 #[serde(default)]
106 pub id: Option<String>,
107 #[serde(default)]
108 pub name: Option<String>,
109 #[serde(default, rename = "type")]
110 pub venue_type: Option<String>,
111 #[serde(default)]
112 pub alternate_names: Option<Vec<String>>,
113 #[serde(default)]
114 pub url: Option<String>,
115}
116
117#[derive(Debug, Clone, Default, Serialize, Deserialize)]
118pub struct OpenAccessPdf {
119 #[serde(default)]
120 pub url: Option<String>,
121 #[serde(default)]
122 pub status: Option<String>,
123}
124
125#[derive(Debug, Clone, Default, Serialize, Deserialize)]
126pub struct S2FieldOfStudy {
127 #[serde(default)]
128 pub category: Option<String>,
129 #[serde(default)]
130 pub source: Option<String>,
131}
132
133#[derive(Debug, Clone, Default, Serialize, Deserialize)]
134pub struct Journal {
135 #[serde(default)]
136 pub name: Option<String>,
137 #[serde(default)]
138 pub pages: Option<String>,
139 #[serde(default)]
140 pub volume: Option<String>,
141}
142
143#[derive(Debug, Clone, Default, Serialize, Deserialize)]
144pub struct CitationStyles {
145 #[serde(default)]
146 pub bibtex: Option<String>,
147}
148
149#[derive(Debug, Clone, Default, Serialize, Deserialize)]
151#[serde(rename_all = "camelCase")]
152pub struct AuthorRef {
153 #[serde(default)]
154 pub author_id: Option<String>,
155 #[serde(default)]
156 pub name: Option<String>,
157}
158
159#[derive(Debug, Clone, Default, Serialize, Deserialize)]
161#[serde(rename_all = "camelCase")]
162pub struct Citation {
163 #[serde(default)]
164 pub citing_paper: Option<Paper>,
165 #[serde(default)]
166 pub contexts: Option<Vec<String>>,
167 #[serde(default)]
168 pub intents: Option<Vec<String>>,
169 #[serde(default)]
170 pub is_influential: Option<bool>,
171}
172
173#[derive(Debug, Clone, Default, Serialize, Deserialize)]
175#[serde(rename_all = "camelCase")]
176pub struct Reference {
177 #[serde(default)]
178 pub cited_paper: Option<Paper>,
179 #[serde(default)]
180 pub contexts: Option<Vec<String>>,
181 #[serde(default)]
182 pub intents: Option<Vec<String>>,
183 #[serde(default)]
184 pub is_influential: Option<bool>,
185}
186
187#[derive(Debug, Clone, Default, Serialize, Deserialize)]
189pub struct Tldr {
190 #[serde(default)]
191 pub model: Option<String>,
192 #[serde(default)]
193 pub text: Option<String>,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct PaperSearchResponse {
203 #[serde(default)]
204 pub total: u64,
205 #[serde(default)]
206 pub offset: Option<u32>,
207 #[serde(default)]
208 pub next: Option<u32>,
209 #[serde(default)]
210 pub data: Vec<Paper>,
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct CitationResponse {
216 #[serde(default)]
217 pub offset: Option<u32>,
218 #[serde(default)]
219 pub next: Option<u32>,
220 #[serde(default)]
221 pub data: Vec<Citation>,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct ReferenceResponse {
227 #[serde(default)]
228 pub offset: Option<u32>,
229 #[serde(default)]
230 pub next: Option<u32>,
231 #[serde(default)]
232 pub data: Vec<Reference>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237#[serde(rename_all = "camelCase")]
238pub struct RecommendationResponse {
239 #[serde(default)]
240 pub recommended_papers: Vec<Paper>,
241}