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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
use serde::{ser::SerializeMap, Deserialize, Serialize, Serializer};
use std::{
collections::HashMap,
fmt::{Display, Formatter},
};
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiException {
/// A string representing the class of exception.
pub exception: String,
/// A human readable error message in English.
pub doc: String,
/// A URL linking to hopefully the relevant documentation.
pub display: String,
}
/// The object is returned by the version endpoint
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Version {
/// The major version of the API
pub api_version: u8,
/// The version of the software providing the API
pub software_version: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Company {
/// The name of the company, in the form provided by the advertiser.
/// A company name is not always available.
pub display_name: Option<String>,
/// A normalised string of the company name. This is not always available.
/// When available, it can be supplied to the search endpoint in the company query string parameter.
pub canonical_name: Option<String>,
/// The total number of job advertisements posted by this company.
/// This will normally only be provided by statistics queries, not search queries.
pub count: Option<usize>,
/// The average salary in job advertisements posted by this company.
/// This will normally only be provided by statistics queries, not search queries.
/// The data may be provided with up to two decimal places, and will have no currency symbol.
pub average_salary: Option<usize>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TopCompanies {
/// A list of Company objects, ordered by the number of advertisements they have in our database.
pub leaderboard: Option<Vec<Company>>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Category {
/// The string which should be passed to search endpoint using the category query parameter.
pub tag: String,
/// A text string describing the category, suitable for display.
pub label: String,
}
/// The object is returned by the categories endpoint
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Categories {
/// An array of all the categories discovered as Category objects.
pub results: Vec<Category>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HistoricalSalary {
/// A hash of salary figures. The key is an ISO 8601 date, omitting the day.
/// For example, 2013-09 indicates September 2013.
/// The salary is averaged and supplied with up to two decimal places but no currency symbol, for example 20000.00, 20000.0 or 20000.
pub month: Option<HashMap<String, f64>>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SalaryHistogram {
/// Returns the current distribution of jobs by salary.
/// Results are returned as an associative array of salaries and vacancies.
/// - Each salary number indicates the lower end of a range.
/// - Each vacancy number is the number of live job ads with a salary in range.
/// It can be used to generate a "histogram distribution" of salaries.
/// This is a hashmap containing the histogram data. The buckets are the hash keys, indicating the lowest salary counted in that particular bucket.
pub histogram: Option<HashMap<String, usize>>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LocationDetail {
/// A description of the location, as an array of strings, each refining the location more than the previous.
/// - Country
/// - Region
/// - Sub-region or city
/// - City, town or suburb
/// Locations may have up to five levels of detail. For example,
/// - UK
/// - South East England
/// - Surrey
/// - Reigate
/// - Leigh
/// This data may be serialised into a series of locationN query string parameters and be supplied to the search and statistical endpoints.
pub area: Option<Vec<String>>,
/// A human readable name for the location, intended for display in applications.
pub display_name: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LocationJobs {
/// The number of jobs available at this location.
pub count: Option<usize>,
/// More detail about the location
pub location: Option<LocationDetail>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct JobGeoData {
/// List of Location objects
pub locations: Option<Vec<LocationJobs>>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Job {
/// A string uniquely identifying this advertisement.
pub id: String,
/// The date the ad was created as defined by the original source of the ad.
/// Where we find an ad without a created date, we use the time we first saw the ad.
/// It is formatted as an ISO 8601 date time string.
pub created: String,
/// A summary of the advertisement.
pub title: String,
/// The details of the advertisement, truncated to 500 characters.
pub description: String,
/// A URL which will redirect to the advertisement as displayed on the advertiser's site.
/// Using this URL send a user to the advertiser's site is necessary to be compliant with Adzuna's terms and conditions.
pub redirect_url: String,
/// The latitude of the workplace, in degrees.
pub latitude: f64,
/// The longitude of the workplace, in degrees.
pub longitude: f64,
/// The category of the advertisement.
pub category: Category,
/// The locality of the advertisement.
pub location: LocationDetail,
/// The bottom end of the pay scale for this job, given in the local currency.
pub salary_min: f64,
/// The top end of the pay scale for this job, given in the local currency.
pub salary_max: f64,
/// A flag indicating if the salary of the job was predicted by Adzuna's 'Jobsworth' technology.
/// Jobsworth predicts salaries for jobs with no advertised salary.
/// Predictions are based on continual analysis of millions of ads. Most of the time predictions are accurate within 10%.
pub salary_is_predicted: String,
/// The company offering the job.
pub company: Company,
/// Either `permanent` or `contract` to indicate whether the job is permanent or just a short-term contract.
pub contract_type: Option<String>,
/// Either `full_time` or `part_time` to indicate the hours of the job.
pub contract_time: Option<String>,
/// TBD
pub adref: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct JobSearchResults {
/// An array of the search results as Job objects.
pub results: Vec<Job>,
/// Number of jobs that were matched
pub count: usize,
/// The mean salary across all the results
pub mean: f64,
}
pub enum SortDirection {
Up,
Down,
}
impl Display for SortDirection {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
SortDirection::Up => {
write!(f, "up")
}
SortDirection::Down => {
write!(f, "down")
}
}
}
}
pub enum SortBy {
Default,
Hybrid,
Date,
Salary,
Relevance,
}
impl Display for SortBy {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match self {
SortBy::Default => {
write!(f, "default")
}
SortBy::Hybrid => {
write!(f, "hybrid")
}
SortBy::Date => {
write!(f, "date")
}
SortBy::Salary => {
write!(f, "salary")
}
SortBy::Relevance => {
write!(f, "relevance")
}
}
}
}
fn location_serialize<S>(locations: &[String], s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut ser = s.serialize_map(Some(8))?;
for (i, location) in locations.iter().enumerate() {
ser.serialize_entry(&format!("location{i}"), location)?;
}
ser.end()
}
#[derive(Debug, Default, Serialize)]
pub struct Parameters {
#[serde(serialize_with = "location_serialize")]
#[serde(flatten)]
pub locations: Vec<String>,
pub category: Option<String>,
pub what: Option<String>,
pub months: Option<usize>,
pub what_and: Option<String>,
pub what_phrase: Option<String>,
pub what_or: Option<String>,
pub what_exclude: Option<String>,
pub title_only: Option<String>,
pub r#where: Option<String>,
pub salary_include_unknown: Option<String>,
pub full_time: Option<String>,
pub part_time: Option<String>,
pub contract: Option<String>,
pub permanent: Option<String>,
pub company: Option<String>,
pub distance: Option<usize>,
pub results_per_page: Option<usize>,
pub max_days_old: Option<usize>,
pub salary_min: Option<usize>,
pub salary_max: Option<usize>,
pub sort_dir: Option<String>,
pub sort_by: Option<String>,
}
pub enum Country {
UnitedKingdom,
UnitedStates,
Austria,
Australia,
Belgium,
Brazil,
Canada,
Switzerland,
Germany,
Spain,
France,
India,
Italy,
Mexico,
Netherlands,
NewZealand,
Poland,
Russia,
Singapore,
SouthAfrica,
}
impl Country {
pub fn to_code(&self) -> &'static str {
match self {
Country::UnitedKingdom => "gb",
Country::UnitedStates => "us",
Country::Austria => "at",
Country::Australia => "au",
Country::Belgium => "be",
Country::Brazil => "br",
Country::Canada => "ca",
Country::Switzerland => "ch",
Country::Germany => "de",
Country::Spain => "es",
Country::France => "fr",
Country::India => "in",
Country::Italy => "it",
Country::Mexico => "mx",
Country::Netherlands => "nl",
Country::NewZealand => "nl",
Country::Poland => "pl",
Country::Russia => "ru",
Country::Singapore => "sg",
Country::SouthAfrica => "za",
}
}
}