Skip to main content

mindat_rs/models/
localities.rs

1//! Locality types for the Mindat API.
2
3use serde::{Deserialize, Serialize};
4
5use super::serde_helpers::{
6    deserialize_i64, deserialize_optional_f64, deserialize_optional_i16, deserialize_optional_i32,
7    deserialize_optional_vec_i32,
8};
9
10/// A locality from the Mindat database.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct Locality {
13    /// Mindat ID.
14    pub id: i32,
15    /// Long ID string.
16    #[serde(default)]
17    pub longid: Option<String>,
18    /// GUID.
19    #[serde(default)]
20    pub guid: Option<String>,
21    /// Locality text/name.
22    #[serde(default)]
23    pub txt: Option<String>,
24    /// Reversed text description.
25    #[serde(default)]
26    pub revtxtd: Option<String>,
27    /// Short description.
28    #[serde(default)]
29    pub description_short: Option<String>,
30    /// Latitude.
31    #[serde(default, deserialize_with = "deserialize_optional_f64")]
32    pub latitude: Option<f64>,
33    /// Longitude.
34    #[serde(default, deserialize_with = "deserialize_optional_f64")]
35    pub longitude: Option<f64>,
36    /// Language-specific text.
37    #[serde(default)]
38    pub langtxt: Option<String>,
39    /// Date added.
40    #[serde(default)]
41    pub dateadd: Option<String>,
42    /// Date modified.
43    #[serde(default)]
44    pub datemodify: Option<String>,
45    /// Elements found at this locality.
46    #[serde(default)]
47    pub elements: Option<String>,
48    /// Country name.
49    #[serde(default)]
50    pub country: Option<String>,
51    /// References.
52    #[serde(default)]
53    pub refs: Option<String>,
54    /// Coordinate system.
55    #[serde(default, deserialize_with = "deserialize_optional_i32")]
56    pub coordsystem: Option<i32>,
57    /// Parent locality ID.
58    #[serde(default, deserialize_with = "deserialize_optional_i32")]
59    pub parent: Option<i32>,
60    /// Links.
61    #[serde(default)]
62    pub links: Option<String>,
63    /// Area.
64    #[serde(default, deserialize_with = "deserialize_optional_i32")]
65    pub area: Option<i32>,
66    /// Non-hierarchical flag.
67    #[serde(default, deserialize_with = "deserialize_optional_i32")]
68    pub non_hierarchical: Option<i32>,
69    /// Age ID.
70    #[serde(default, deserialize_with = "deserialize_optional_i32")]
71    pub age: Option<i32>,
72    /// Meteorite type.
73    #[serde(default, deserialize_with = "deserialize_optional_i32")]
74    pub meteorite_type: Option<i32>,
75    /// Company ID.
76    #[serde(default, deserialize_with = "deserialize_optional_i32")]
77    pub company: Option<i32>,
78    /// Company 2 ID.
79    #[serde(default, deserialize_with = "deserialize_optional_i32")]
80    pub company2: Option<i32>,
81    /// Locality status ID.
82    #[serde(default, deserialize_with = "deserialize_optional_i32")]
83    pub loc_status: Option<i32>,
84    /// Locality group.
85    #[serde(default, deserialize_with = "deserialize_optional_i32")]
86    pub loc_group: Option<i32>,
87    /// Status year.
88    #[serde(default)]
89    pub status_year: Option<String>,
90    /// Company year.
91    #[serde(default)]
92    pub company_year: Option<String>,
93    /// Discovered before.
94    #[serde(default, deserialize_with = "deserialize_optional_i32")]
95    pub discovered_before: Option<i32>,
96    /// Discovery year.
97    #[serde(default, deserialize_with = "deserialize_optional_i32")]
98    pub discovery_year: Option<i32>,
99    /// Discovery year type.
100    #[serde(default)]
101    pub discovery_year_type: Option<String>,
102    /// Hierarchy level.
103    #[serde(default, deserialize_with = "deserialize_optional_i32")]
104    pub level: Option<i32>,
105    /// Included localities.
106    #[serde(default)]
107    pub locsinclude: Option<String>,
108    /// Excluded localities.
109    #[serde(default)]
110    pub locsexclude: Option<String>,
111    /// Wikipedia link.
112    #[serde(default)]
113    pub wikipedia: Option<String>,
114    /// OSM ID.
115    #[serde(default)]
116    pub osmid: Option<String>,
117    /// Geonames ID.
118    #[serde(default, deserialize_with = "deserialize_optional_i32")]
119    pub geonames: Option<i32>,
120    /// Timestamp.
121    #[serde(default)]
122    pub timestamp: Option<String>,
123    /// Geomaterials at this locality (when expanded).
124    #[serde(default, deserialize_with = "deserialize_optional_vec_i32")]
125    pub geomaterials: Option<Vec<i32>>,
126}
127
128/// Builder for locality query parameters.
129#[derive(Debug, Clone, Default)]
130pub struct LocalitiesQuery {
131    /// Country name filter.
132    pub country: Option<String>,
133    /// Locality name contains.
134    pub txt: Option<String>,
135    /// Description contains.
136    pub description: Option<String>,
137    /// Include elements (comma-separated).
138    pub elements_inc: Option<String>,
139    /// Exclude elements (comma-separated).
140    pub elements_exc: Option<String>,
141    /// Filter by IDs.
142    pub id_in: Option<Vec<i32>>,
143    /// Only localities at or above this hierarchy level.
144    pub level_gte: Option<i32>,
145    /// Only localities at or below this hierarchy level.
146    pub level_lte: Option<i32>,
147    /// Only localities with at least this many sub-localities.
148    pub sublocs_gte: Option<i32>,
149    /// Only localities with at most this many sub-localities.
150    pub sublocs_lte: Option<i32>,
151    /// Filter by non-hierarchical flag.
152    pub non_hierarchial: Option<i32>,
153    /// Description text starts with (case-insensitive).
154    pub revtxtd_istartswith: Option<String>,
155    /// Updated after datetime.
156    pub updated_at: Option<String>,
157    /// Fields to include.
158    pub fields: Option<String>,
159    /// Fields to omit.
160    pub omit: Option<String>,
161    /// Fields to expand.
162    pub expand: Option<Vec<String>>,
163    /// Page size (number of results per page).
164    pub page_size: Option<i32>,
165    /// Page number for pagination.
166    pub page: Option<i32>,
167}
168
169impl LocalitiesQuery {
170    /// Create a new empty query.
171    pub fn new() -> Self {
172        Self::default()
173    }
174
175    /// Filter by country name.
176    pub fn country(mut self, country: impl Into<String>) -> Self {
177        self.country = Some(country.into());
178        self
179    }
180
181    /// Filter by locality name.
182    pub fn name_contains(mut self, txt: impl Into<String>) -> Self {
183        self.txt = Some(txt.into());
184        self
185    }
186
187    /// Filter by description.
188    pub fn description_contains(mut self, desc: impl Into<String>) -> Self {
189        self.description = Some(desc.into());
190        self
191    }
192
193    /// Filter by included elements.
194    pub fn with_elements(mut self, elements: impl Into<String>) -> Self {
195        self.elements_inc = Some(elements.into());
196        self
197    }
198
199    /// Filter by excluded elements.
200    pub fn without_elements(mut self, elements: impl Into<String>) -> Self {
201        self.elements_exc = Some(elements.into());
202        self
203    }
204
205    /// Select specific fields.
206    pub fn select_fields(mut self, fields: impl Into<String>) -> Self {
207        self.fields = Some(fields.into());
208        self
209    }
210
211    /// Omit specific fields.
212    pub fn omit_fields(mut self, fields: impl Into<String>) -> Self {
213        self.omit = Some(fields.into());
214        self
215    }
216
217    /// Expand related fields.
218    pub fn expand_fields(mut self, fields: Vec<String>) -> Self {
219        self.expand = Some(fields);
220        self
221    }
222
223    /// Filter by hierarchy level range (inclusive).
224    pub fn level_range(mut self, min: i32, max: i32) -> Self {
225        self.level_gte = Some(min);
226        self.level_lte = Some(max);
227        self
228    }
229
230    /// Set page size (number of results per page).
231    pub fn page_size(mut self, size: i32) -> Self {
232        self.page_size = Some(size);
233        self
234    }
235
236    /// Set page number for pagination.
237    pub fn page(mut self, page: i32) -> Self {
238        self.page = Some(page);
239        self
240    }
241}
242
243/// Locality age information.
244#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct LocalityAge {
246    /// Age ID.
247    pub age_id: i32,
248    /// Age MA value.
249    #[serde(default, deserialize_with = "deserialize_optional_f64")]
250    pub age_mav: Option<f64>,
251    /// Age PM value.
252    #[serde(default, deserialize_with = "deserialize_optional_f64")]
253    pub age_pmv: Option<f64>,
254    /// Age MA2 value.
255    #[serde(default, deserialize_with = "deserialize_optional_f64")]
256    pub age_ma2v: Option<f64>,
257    /// Age PM2 value.
258    #[serde(default, deserialize_with = "deserialize_optional_f64")]
259    pub age_pm2v: Option<f64>,
260    /// Age method.
261    #[serde(default)]
262    pub agemethod: Option<String>,
263    /// Age reference.
264    #[serde(default)]
265    pub agereference: Option<String>,
266    /// Age MA string.
267    #[serde(default)]
268    pub age_ma: Option<String>,
269    /// Age PM string.
270    #[serde(default)]
271    pub age_pm: Option<String>,
272    /// Age MA2 string.
273    #[serde(default)]
274    pub age_ma2: Option<String>,
275    /// Age PM2 string.
276    #[serde(default)]
277    pub age_pm2: Option<String>,
278    /// Ages 1.
279    #[serde(default, deserialize_with = "deserialize_optional_i32")]
280    pub ages1: Option<i32>,
281    /// Ages 2.
282    #[serde(default, deserialize_with = "deserialize_optional_i32")]
283    pub ages2: Option<i32>,
284    /// Age type.
285    #[serde(default, deserialize_with = "deserialize_optional_i32")]
286    pub age_type: Option<i32>,
287}
288
289/// Locality status information.
290#[derive(Debug, Clone, Serialize, Deserialize)]
291pub struct LocalityStatus {
292    /// Status ID.
293    pub ls_id: i32,
294    /// Status text.
295    pub ls_text: String,
296    /// Historical flag.
297    #[serde(default, deserialize_with = "deserialize_optional_i32")]
298    pub ls_historical: Option<i32>,
299    /// Wide flag.
300    #[serde(default, deserialize_with = "deserialize_optional_i32")]
301    pub ls_wide: Option<i32>,
302}
303
304/// Locality type information.
305#[derive(Debug, Clone, Serialize, Deserialize)]
306pub struct LocalityType {
307    /// Type ID.
308    pub lt_id: i32,
309    /// Type text.
310    pub lt_text: String,
311    /// Parent type ID.
312    #[serde(default, deserialize_with = "deserialize_optional_i32")]
313    pub lt_parent: Option<i32>,
314    /// Sort order.
315    #[serde(default, deserialize_with = "deserialize_optional_i16")]
316    pub lt_sortorder: Option<i16>,
317    /// Erratic flag.
318    #[serde(default, deserialize_with = "deserialize_optional_i32")]
319    pub lt_erratic: Option<i32>,
320    /// Area flag.
321    #[serde(default, deserialize_with = "deserialize_optional_i32")]
322    pub lt_area: Option<i32>,
323    /// Underground flag.
324    #[serde(default, deserialize_with = "deserialize_optional_i32")]
325    pub lt_underground: Option<i32>,
326}
327
328/// A translated locality name (`/locality-translations/`).
329#[derive(Debug, Clone, Serialize, Deserialize)]
330pub struct LocalityTranslation {
331    /// Translation ID.
332    #[serde(deserialize_with = "deserialize_i64")]
333    pub lt_id: i64,
334    /// Locality ID.
335    #[serde(default, deserialize_with = "deserialize_optional_i32")]
336    pub lt_loc: Option<i32>,
337    /// Translated text.
338    #[serde(default)]
339    pub lt_text: Option<String>,
340    /// Translation datetime.
341    #[serde(default)]
342    pub lt_datetime: Option<String>,
343    /// Contributing user ID.
344    #[serde(default, deserialize_with = "deserialize_optional_i32")]
345    pub lt_uid: Option<i32>,
346    /// ISO language code.
347    #[serde(default)]
348    pub lt_iso: Option<String>,
349    /// Important flag.
350    #[serde(default, deserialize_with = "deserialize_optional_i32")]
351    pub lt_important: Option<i32>,
352}
353
354/// Builder for `/locality-translations/` query parameters.
355#[derive(Debug, Clone, Default)]
356pub struct LocalityTranslationsQuery {
357    /// Filter by locality ID.
358    pub lt_loc: Option<i32>,
359    /// Filter by ISO language code.
360    pub lt_iso: Option<String>,
361    /// Filter by translated text.
362    pub lt_text: Option<String>,
363    /// Filter by important flag.
364    pub lt_important: Option<i32>,
365    /// Modified at/after datetime.
366    pub lt_datetime_gte: Option<String>,
367    /// Ordering field.
368    pub ordering: Option<String>,
369    /// Page number.
370    pub page: Option<i32>,
371    /// Page size.
372    pub page_size: Option<i32>,
373}
374
375impl LocalityTranslationsQuery {
376    /// Create a new empty query.
377    pub fn new() -> Self {
378        Self::default()
379    }
380
381    /// Filter to translations for a given locality.
382    pub fn locality(mut self, locality_id: i32) -> Self {
383        self.lt_loc = Some(locality_id);
384        self
385    }
386
387    /// Filter by ISO language code.
388    pub fn language(mut self, iso: impl Into<String>) -> Self {
389        self.lt_iso = Some(iso.into());
390        self
391    }
392
393    /// Set page number.
394    pub fn page(mut self, page: i32) -> Self {
395        self.page = Some(page);
396        self
397    }
398
399    /// Set page size.
400    pub fn page_size(mut self, size: i32) -> Self {
401        self.page_size = Some(size);
402        self
403    }
404}