Skip to main content

prelude_xml_parser/native/
common.rs

1#[cfg(not(feature = "python"))]
2/// The attributes on the `export_from_vision_EDC` root element: who produced the export, when, and
3/// how much of the study it covers.
4#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
5pub struct Export {
6    #[serde(rename = "date")]
7    #[serde(alias = "@date")]
8    #[serde(alias = "date")]
9    #[serde(
10        default,
11        deserialize_with = "deserialize_empty_string_as_none_datetime"
12    )]
13    pub date: Option<DateTime<Utc>>,
14
15    #[serde(rename = "createdBy")]
16    #[serde(alias = "@createdBy")]
17    #[serde(alias = "createdBy")]
18    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
19    pub created_by: Option<String>,
20
21    #[serde(rename = "role")]
22    #[serde(alias = "@role")]
23    #[serde(alias = "role")]
24    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
25    pub role: Option<String>,
26
27    #[serde(rename = "numberSubjectsProcessed")]
28    #[serde(alias = "@numberSubjectsProcessed")]
29    #[serde(alias = "numberSubjectsProcessed")]
30    #[serde(default)]
31    pub number_subjects_processed: Option<usize>,
32
33    /// Present when the export was split, e.g. `"1 of 6"`.
34    #[serde(rename = "pageNumber")]
35    #[serde(alias = "@pageNumber")]
36    #[serde(alias = "pageNumber")]
37    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
38    pub page_number: Option<String>,
39}
40
41#[cfg(feature = "python")]
42/// The attributes on the `export_from_vision_EDC` root element: who produced the export, when, and
43/// how much of the study it covers.
44#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
45#[pyclass(skip_from_py_object)]
46pub struct Export {
47    #[serde(rename = "date")]
48    #[serde(alias = "@date")]
49    #[serde(alias = "date")]
50    #[serde(
51        default,
52        deserialize_with = "deserialize_empty_string_as_none_datetime"
53    )]
54    pub date: Option<DateTime<Utc>>,
55
56    #[serde(rename = "createdBy")]
57    #[serde(alias = "@createdBy")]
58    #[serde(alias = "createdBy")]
59    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
60    pub created_by: Option<String>,
61
62    #[serde(rename = "role")]
63    #[serde(alias = "@role")]
64    #[serde(alias = "role")]
65    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
66    pub role: Option<String>,
67
68    #[serde(rename = "numberSubjectsProcessed")]
69    #[serde(alias = "@numberSubjectsProcessed")]
70    #[serde(alias = "numberSubjectsProcessed")]
71    #[serde(default)]
72    pub number_subjects_processed: Option<usize>,
73
74    /// Present when the export was split, e.g. `"1 of 6"`.
75    #[serde(rename = "pageNumber")]
76    #[serde(alias = "@pageNumber")]
77    #[serde(alias = "pageNumber")]
78    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
79    pub page_number: Option<String>,
80}
81
82use std::sync::Arc;
83
84use chrono::{DateTime, Utc};
85use serde::{Deserialize, Serialize};
86
87#[cfg(feature = "python")]
88use pyo3::{
89    prelude::*,
90    types::{PyDateTime, PyDict},
91};
92
93use quick_xml::events::BytesStart;
94
95use crate::native::deserializers::{
96    attribute_string, checked_datetime, deserialize_empty_string_as_none,
97    deserialize_empty_string_as_none_arc, deserialize_empty_string_as_none_datetime,
98    optional_datetime, optional_string, visit_attributes, Interner,
99};
100
101#[cfg(feature = "python")]
102use crate::native::deserializers::{to_py_datetime, to_py_datetime_option};
103
104#[cfg(not(feature = "python"))]
105#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
106pub struct Value {
107    #[serde(rename = "by")]
108    #[serde(alias = "@by")]
109    #[serde(alias = "by")]
110    pub by: Arc<str>,
111
112    #[serde(rename = "byUniqueId")]
113    #[serde(alias = "@byUniqueId")]
114    #[serde(alias = "byUniqueId")]
115    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
116    pub by_unique_id: Option<Arc<str>>,
117    #[serde(rename = "role")]
118    #[serde(alias = "@role")]
119    #[serde(alias = "role")]
120    pub role: Arc<str>,
121    #[serde(rename = "when")]
122    #[serde(alias = "@when")]
123    #[serde(alias = "when")]
124    pub when: Option<DateTime<Utc>>,
125
126    #[serde(rename = "value")]
127    #[serde(alias = "$text")]
128    #[serde(alias = "#text")]
129    #[serde(alias = "value")]
130    #[serde(default)]
131    pub value: String,
132}
133
134#[cfg(feature = "python")]
135#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
136#[pyclass(skip_from_py_object)]
137pub struct Value {
138    #[serde(rename = "by")]
139    #[serde(alias = "@by")]
140    #[serde(alias = "by")]
141    pub by: Arc<str>,
142
143    #[serde(rename = "byUniqueId")]
144    #[serde(alias = "@byUniqueId")]
145    #[serde(alias = "byUniqueId")]
146    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
147    pub by_unique_id: Option<Arc<str>>,
148    #[serde(rename = "role")]
149    #[serde(alias = "@role")]
150    #[serde(alias = "role")]
151    pub role: Arc<str>,
152    #[serde(rename = "when")]
153    #[serde(alias = "@when")]
154    #[serde(alias = "when")]
155    pub when: Option<DateTime<Utc>>,
156
157    #[serde(rename = "value")]
158    #[serde(alias = "$text")]
159    #[serde(alias = "#text")]
160    #[serde(alias = "value")]
161    #[serde(default)]
162    pub value: String,
163}
164
165#[cfg(feature = "python")]
166#[pymethods]
167impl Value {
168    #[getter]
169    fn by(&self) -> PyResult<String> {
170        Ok(self.by.to_string())
171    }
172
173    #[getter]
174    fn by_unique_id(&self) -> PyResult<Option<String>> {
175        Ok(self.by_unique_id.as_deref().map(str::to_string))
176    }
177
178    #[getter]
179    fn role(&self) -> PyResult<String> {
180        Ok(self.role.to_string())
181    }
182
183    #[getter]
184    fn when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
185        to_py_datetime_option(py, &self.when)
186    }
187
188    #[getter]
189    fn value(&self) -> PyResult<String> {
190        Ok(self.value.clone())
191    }
192
193    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
194        let dict = PyDict::new(py);
195        dict.set_item("by", &*self.by)?;
196        dict.set_item("by_unique_id", self.by_unique_id.as_deref())?;
197        dict.set_item("role", &*self.role)?;
198        dict.set_item("when", to_py_datetime_option(py, &self.when)?)?;
199        dict.set_item("value", &self.value)?;
200
201        Ok(dict)
202    }
203}
204
205#[cfg(not(feature = "python"))]
206#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
207pub struct Reason {
208    #[serde(rename = "by")]
209    #[serde(alias = "@by")]
210    #[serde(alias = "by")]
211    pub by: Arc<str>,
212
213    #[serde(rename = "byUniqueId")]
214    #[serde(alias = "@byUniqueId")]
215    #[serde(alias = "byUniqueId")]
216    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
217    pub by_unique_id: Option<Arc<str>>,
218
219    #[serde(rename = "role")]
220    #[serde(alias = "@role")]
221    #[serde(alias = "role")]
222    pub role: Arc<str>,
223    #[serde(rename = "when")]
224    #[serde(alias = "@when")]
225    #[serde(alias = "when")]
226    pub when: Option<DateTime<Utc>>,
227
228    #[serde(rename = "value")]
229    #[serde(alias = "$text")]
230    #[serde(alias = "#text")]
231    #[serde(alias = "value")]
232    #[serde(default)]
233    pub value: String,
234}
235
236#[cfg(feature = "python")]
237#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
238#[pyclass(skip_from_py_object)]
239pub struct Reason {
240    #[serde(rename = "by")]
241    #[serde(alias = "@by")]
242    #[serde(alias = "by")]
243    pub by: Arc<str>,
244
245    #[serde(rename = "byUniqueId")]
246    #[serde(alias = "@byUniqueId")]
247    #[serde(alias = "byUniqueId")]
248    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
249    pub by_unique_id: Option<Arc<str>>,
250
251    #[serde(rename = "role")]
252    #[serde(alias = "@role")]
253    #[serde(alias = "role")]
254    pub role: Arc<str>,
255    #[serde(rename = "when")]
256    #[serde(alias = "@when")]
257    #[serde(alias = "when")]
258    pub when: Option<DateTime<Utc>>,
259
260    #[serde(rename = "value")]
261    #[serde(alias = "$text")]
262    #[serde(alias = "#text")]
263    #[serde(alias = "value")]
264    #[serde(default)]
265    pub value: String,
266}
267
268#[cfg(feature = "python")]
269#[pymethods]
270impl Reason {
271    #[getter]
272    fn by(&self) -> PyResult<String> {
273        Ok(self.by.to_string())
274    }
275
276    #[getter]
277    fn by_unique_id(&self) -> PyResult<Option<String>> {
278        Ok(self.by_unique_id.as_deref().map(str::to_string))
279    }
280
281    #[getter]
282    fn role(&self) -> PyResult<String> {
283        Ok(self.role.to_string())
284    }
285
286    #[getter]
287    fn when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
288        to_py_datetime_option(py, &self.when)
289    }
290
291    #[getter]
292    fn value(&self) -> PyResult<String> {
293        Ok(self.value.clone())
294    }
295
296    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
297        let dict = PyDict::new(py);
298        dict.set_item("by", &*self.by)?;
299        dict.set_item("by_unique_id", self.by_unique_id.as_deref())?;
300        dict.set_item("role", &*self.role)?;
301        dict.set_item("when", to_py_datetime_option(py, &self.when)?)?;
302        dict.set_item("value", &self.value)?;
303
304        Ok(dict)
305    }
306}
307
308#[cfg(not(feature = "python"))]
309#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
310pub struct Entry {
311    #[serde(rename = "entryId")]
312    #[serde(alias = "@id")]
313    #[serde(alias = "entryId")]
314    pub entry_id: Arc<str>,
315
316    #[serde(rename = "reviewedBy")]
317    #[serde(alias = "@reviewedBy")]
318    #[serde(alias = "reviewedBy")]
319    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
320    pub reviewed_by: Option<String>,
321
322    #[serde(rename = "reviewedByUniqueId")]
323    #[serde(alias = "@reviewedByUniqueId")]
324    #[serde(alias = "reviewedByUniqueId")]
325    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
326    pub reviewed_by_unique_id: Option<String>,
327
328    #[serde(rename = "reviewedByWhen")]
329    #[serde(alias = "@reviewedByWhen")]
330    #[serde(alias = "reviewedByWhen")]
331    #[serde(
332        default,
333        deserialize_with = "deserialize_empty_string_as_none_datetime"
334    )]
335    pub reviewed_by_when: Option<DateTime<Utc>>,
336
337    pub value: Option<Value>,
338    pub reason: Option<Reason>,
339}
340
341#[cfg(feature = "python")]
342#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
343#[pyclass(skip_from_py_object)]
344pub struct Entry {
345    #[serde(rename = "entryId")]
346    #[serde(alias = "@id")]
347    #[serde(alias = "entryId")]
348    pub entry_id: Arc<str>,
349
350    #[serde(rename = "reviewedBy")]
351    #[serde(alias = "@reviewedBy")]
352    #[serde(alias = "reviewedBy")]
353    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
354    pub reviewed_by: Option<String>,
355
356    #[serde(rename = "reviewedByUniqueId")]
357    #[serde(alias = "@reviewedByUniqueId")]
358    #[serde(alias = "reviewedByUniqueId")]
359    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
360    pub reviewed_by_unique_id: Option<String>,
361
362    #[serde(rename = "reviewedByWhen")]
363    #[serde(alias = "@reviewedByWhen")]
364    #[serde(alias = "reviewedByWhen")]
365    #[serde(
366        default,
367        deserialize_with = "deserialize_empty_string_as_none_datetime"
368    )]
369    pub reviewed_by_when: Option<DateTime<Utc>>,
370
371    pub value: Option<Value>,
372    pub reason: Option<Reason>,
373}
374
375#[cfg(feature = "python")]
376#[pymethods]
377impl Entry {
378    #[getter]
379    fn entry_id(&self) -> PyResult<String> {
380        Ok(self.entry_id.to_string())
381    }
382
383    #[getter]
384    fn reviewed_by(&self) -> PyResult<Option<String>> {
385        Ok(self.reviewed_by.clone())
386    }
387
388    #[getter]
389    fn reviewed_by_unique_id(&self) -> PyResult<Option<String>> {
390        Ok(self.reviewed_by_unique_id.clone())
391    }
392
393    #[getter]
394    fn reviewed_by_when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
395        to_py_datetime_option(py, &self.reviewed_by_when)
396    }
397
398    #[getter]
399    fn value(&self) -> PyResult<Option<Value>> {
400        Ok(self.value.clone())
401    }
402
403    #[getter]
404    fn reason(&self) -> PyResult<Option<Reason>> {
405        Ok(self.reason.clone())
406    }
407
408    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
409        let dict = PyDict::new(py);
410        dict.set_item("entry_id", &*self.entry_id)?;
411        dict.set_item("reviewed_by", &self.reviewed_by)?;
412        dict.set_item("reviewed_by_unique_id", &self.reviewed_by_unique_id)?;
413        dict.set_item(
414            "reviewed_by_when",
415            to_py_datetime_option(py, &self.reviewed_by_when)?,
416        )?;
417        if let Some(value) = &self.value {
418            dict.set_item("value", value.to_dict(py)?)?;
419        } else {
420            dict.set_item("value", py.None())?;
421        }
422        if let Some(reason) = &self.reason {
423            dict.set_item("reason", reason.to_dict(py)?)?;
424        } else {
425            dict.set_item("reason", py.None())?;
426        }
427
428        Ok(dict)
429    }
430}
431
432#[cfg(not(feature = "python"))]
433#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
434pub struct Comment {
435    #[serde(rename = "commentId")]
436    #[serde(alias = "@id")]
437    #[serde(alias = "commentId")]
438    pub comment_id: String,
439
440    #[serde(rename = "reviewedBy")]
441    #[serde(alias = "@reviewedBy")]
442    #[serde(alias = "reviewedBy")]
443    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
444    pub reviewed_by: Option<String>,
445
446    #[serde(rename = "reviewedByUniqueId")]
447    #[serde(alias = "@reviewedByUniqueId")]
448    #[serde(alias = "reviewedByUniqueId")]
449    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
450    pub reviewed_by_unique_id: Option<String>,
451
452    #[serde(rename = "reviewedByWhen")]
453    #[serde(alias = "@reviewedByWhen")]
454    #[serde(alias = "reviewedByWhen")]
455    #[serde(
456        default,
457        deserialize_with = "deserialize_empty_string_as_none_datetime"
458    )]
459    pub reviewed_by_when: Option<DateTime<Utc>>,
460
461    pub value: Option<Value>,
462}
463
464#[cfg(feature = "python")]
465#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
466#[pyclass(skip_from_py_object)]
467pub struct Comment {
468    #[serde(rename = "commentId")]
469    #[serde(alias = "@id")]
470    #[serde(alias = "commentId")]
471    pub comment_id: String,
472
473    #[serde(rename = "reviewedBy")]
474    #[serde(alias = "@reviewedBy")]
475    #[serde(alias = "reviewedBy")]
476    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
477    pub reviewed_by: Option<String>,
478
479    #[serde(rename = "reviewedByUniqueId")]
480    #[serde(alias = "@reviewedByUniqueId")]
481    #[serde(alias = "reviewedByUniqueId")]
482    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
483    pub reviewed_by_unique_id: Option<String>,
484
485    #[serde(rename = "reviewedByWhen")]
486    #[serde(alias = "@reviewedByWhen")]
487    #[serde(alias = "reviewedByWhen")]
488    #[serde(
489        default,
490        deserialize_with = "deserialize_empty_string_as_none_datetime"
491    )]
492    pub reviewed_by_when: Option<DateTime<Utc>>,
493
494    pub value: Option<Value>,
495}
496
497#[cfg(feature = "python")]
498#[pymethods]
499impl Query {
500    #[getter]
501    fn query_id(&self) -> PyResult<String> {
502        Ok(self.query_id.to_string())
503    }
504
505    #[getter]
506    fn reviewed_by(&self) -> PyResult<Option<String>> {
507        Ok(self.reviewed_by.clone())
508    }
509
510    #[getter]
511    fn reviewed_by_unique_id(&self) -> PyResult<Option<String>> {
512        Ok(self.reviewed_by_unique_id.clone())
513    }
514
515    #[getter]
516    fn reviewed_by_when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
517        to_py_datetime_option(py, &self.reviewed_by_when)
518    }
519
520    #[getter]
521    fn value(&self) -> PyResult<Option<Value>> {
522        Ok(self.value.clone())
523    }
524
525    #[getter]
526    fn answer(&self) -> PyResult<Option<Value>> {
527        Ok(self.answer.clone())
528    }
529
530    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
531        let dict = PyDict::new(py);
532        dict.set_item("query_id", &*self.query_id)?;
533        dict.set_item("reviewed_by", &self.reviewed_by)?;
534        dict.set_item("reviewed_by_unique_id", &self.reviewed_by_unique_id)?;
535        dict.set_item(
536            "reviewed_by_when",
537            to_py_datetime_option(py, &self.reviewed_by_when)?,
538        )?;
539
540        match &self.value {
541            Some(value) => dict.set_item("value", value.to_dict(py)?)?,
542            None => dict.set_item("value", py.None())?,
543        }
544
545        match &self.answer {
546            Some(answer) => dict.set_item("answer", answer.to_dict(py)?)?,
547            None => dict.set_item("answer", py.None())?,
548        }
549
550        Ok(dict)
551    }
552}
553
554#[cfg(feature = "python")]
555#[pymethods]
556impl File {
557    #[getter]
558    fn name(&self) -> PyResult<String> {
559        Ok(self.name.to_string())
560    }
561
562    #[getter]
563    fn file_type(&self) -> PyResult<String> {
564        Ok(self.file_type.to_string())
565    }
566
567    #[getter]
568    fn data_type(&self) -> PyResult<Option<String>> {
569        Ok(self.data_type.as_deref().map(str::to_string))
570    }
571
572    #[getter]
573    fn error_code(&self) -> PyResult<String> {
574        Ok(self.error_code.to_string())
575    }
576
577    #[getter]
578    fn when_created<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
579        to_py_datetime_option(py, &self.when_created)
580    }
581
582    #[getter]
583    fn keep_history(&self) -> PyResult<bool> {
584        Ok(self.keep_history)
585    }
586
587    #[getter]
588    fn file_location(&self) -> PyResult<Option<String>> {
589        Ok(self.file_location.clone())
590    }
591
592    #[getter]
593    fn size(&self) -> PyResult<Option<usize>> {
594        Ok(self.size)
595    }
596
597    #[getter]
598    fn entries(&self) -> PyResult<Option<Vec<Entry>>> {
599        Ok(self.entries.as_deref().cloned())
600    }
601
602    #[getter]
603    fn comments(&self) -> PyResult<Option<Vec<Comment>>> {
604        Ok(self.comments.as_deref().cloned())
605    }
606
607    #[getter]
608    fn queries(&self) -> PyResult<Option<Vec<Query>>> {
609        Ok(self.queries.as_deref().cloned())
610    }
611
612    #[getter]
613    fn download_history(&self) -> PyResult<Option<Vec<Comment>>> {
614        Ok(self.download_history.as_deref().cloned())
615    }
616
617    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
618        let dict = PyDict::new(py);
619        dict.set_item("name", &*self.name)?;
620        dict.set_item("file_type", &*self.file_type)?;
621        dict.set_item("data_type", self.data_type.as_deref())?;
622        dict.set_item("error_code", &*self.error_code)?;
623        dict.set_item(
624            "when_created",
625            to_py_datetime_option(py, &self.when_created)?,
626        )?;
627        dict.set_item("keep_history", self.keep_history)?;
628        dict.set_item("file_location", &self.file_location)?;
629        dict.set_item("size", self.size)?;
630
631        for (key, items) in [(
632            "entries",
633            self.entries.as_deref().map(|v| {
634                v.iter()
635                    .map(|x| x.to_dict(py))
636                    .collect::<PyResult<Vec<_>>>()
637            }),
638        )] {
639            match items {
640                Some(items) => dict.set_item(key, items?)?,
641                None => dict.set_item(key, py.None())?,
642            }
643        }
644
645        match self.comments.as_deref() {
646            Some(items) => dict.set_item(
647                "comments",
648                items
649                    .iter()
650                    .map(|x| x.to_dict(py))
651                    .collect::<PyResult<Vec<_>>>()?,
652            )?,
653            None => dict.set_item("comments", py.None())?,
654        }
655
656        match self.queries.as_deref() {
657            Some(items) => dict.set_item(
658                "queries",
659                items
660                    .iter()
661                    .map(|x| x.to_dict(py))
662                    .collect::<PyResult<Vec<_>>>()?,
663            )?,
664            None => dict.set_item("queries", py.None())?,
665        }
666
667        match self.download_history.as_deref() {
668            Some(items) => dict.set_item(
669                "download_history",
670                items
671                    .iter()
672                    .map(|x| x.to_dict(py))
673                    .collect::<PyResult<Vec<_>>>()?,
674            )?,
675            None => dict.set_item("download_history", py.None())?,
676        }
677
678        Ok(dict)
679    }
680}
681
682#[cfg(feature = "python")]
683#[pymethods]
684impl Comment {
685    #[getter]
686    fn comment_id(&self) -> PyResult<String> {
687        Ok(self.comment_id.clone())
688    }
689
690    #[getter]
691    fn value(&self) -> PyResult<Option<Value>> {
692        Ok(self.value.clone())
693    }
694
695    #[getter]
696    fn reviewed_by(&self) -> PyResult<Option<String>> {
697        Ok(self.reviewed_by.clone())
698    }
699
700    #[getter]
701    fn reviewed_by_unique_id(&self) -> PyResult<Option<String>> {
702        Ok(self.reviewed_by_unique_id.clone())
703    }
704
705    #[getter]
706    fn reviewed_by_when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
707        to_py_datetime_option(py, &self.reviewed_by_when)
708    }
709
710    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
711        let dict = PyDict::new(py);
712        dict.set_item("comment_id", &self.comment_id)?;
713        dict.set_item("reviewed_by", &self.reviewed_by)?;
714        dict.set_item("reviewed_by_unique_id", &self.reviewed_by_unique_id)?;
715        dict.set_item(
716            "reviewed_by_when",
717            to_py_datetime_option(py, &self.reviewed_by_when)?,
718        )?;
719        if let Some(value) = &self.value {
720            dict.set_item("value", value.to_dict(py)?)?;
721        } else {
722            dict.set_item("value", py.None())?;
723        }
724
725        Ok(dict)
726    }
727}
728
729#[cfg(not(feature = "python"))]
730#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
731pub struct Query {
732    #[serde(rename = "queryId")]
733    #[serde(alias = "@id")]
734    #[serde(alias = "queryId")]
735    pub query_id: Arc<str>,
736
737    #[serde(rename = "reviewedBy")]
738    #[serde(alias = "@reviewedBy")]
739    #[serde(alias = "reviewedBy")]
740    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
741    pub reviewed_by: Option<String>,
742
743    #[serde(rename = "reviewedByUniqueId")]
744    #[serde(alias = "@reviewedByUniqueId")]
745    #[serde(alias = "reviewedByUniqueId")]
746    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
747    pub reviewed_by_unique_id: Option<String>,
748
749    #[serde(rename = "reviewedByWhen")]
750    #[serde(alias = "@reviewedByWhen")]
751    #[serde(alias = "reviewedByWhen")]
752    #[serde(
753        default,
754        deserialize_with = "deserialize_empty_string_as_none_datetime"
755    )]
756    pub reviewed_by_when: Option<DateTime<Utc>>,
757
758    pub value: Option<Value>,
759    pub answer: Option<Value>,
760}
761
762#[cfg(not(feature = "python"))]
763#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
764pub struct File {
765    #[serde(rename = "name")]
766    #[serde(alias = "@name")]
767    #[serde(alias = "name")]
768    pub name: Arc<str>,
769
770    #[serde(rename = "fileType")]
771    #[serde(alias = "@type")]
772    #[serde(alias = "fileType")]
773    pub file_type: Arc<str>,
774
775    #[serde(rename = "dataType")]
776    #[serde(alias = "@dataType")]
777    #[serde(alias = "dataType")]
778    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
779    pub data_type: Option<Arc<str>>,
780
781    #[serde(rename = "errorCode")]
782    #[serde(alias = "@errorCode")]
783    #[serde(alias = "errorCode")]
784    pub error_code: Arc<str>,
785
786    #[serde(rename = "whenCreated")]
787    #[serde(alias = "@whenCreated")]
788    #[serde(alias = "whenCreated")]
789    pub when_created: Option<DateTime<Utc>>,
790
791    #[serde(rename = "keepHistory")]
792    #[serde(alias = "@keepHistory")]
793    #[serde(alias = "keepHistory")]
794    pub keep_history: bool,
795
796    #[serde(rename = "fileLocation")]
797    #[serde(alias = "@fileLocation")]
798    #[serde(alias = "fileLocation")]
799    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
800    pub file_location: Option<String>,
801
802    #[serde(rename = "size")]
803    #[serde(alias = "@size")]
804    #[serde(alias = "size")]
805    #[serde(default)]
806    pub size: Option<usize>,
807
808    #[serde(alias = "entry")]
809    pub entries: Option<Arc<Vec<Entry>>>,
810
811    #[serde(alias = "comment")]
812    pub comments: Option<Arc<Vec<Comment>>>,
813
814    #[serde(alias = "query")]
815    pub queries: Option<Arc<Vec<Query>>>,
816
817    #[serde(rename = "downloadHistory")]
818    #[serde(alias = "downloadHistory")]
819    pub download_history: Option<Arc<Vec<Comment>>>,
820}
821
822#[cfg(feature = "python")]
823#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
824#[pyclass(skip_from_py_object)]
825pub struct Query {
826    #[serde(rename = "queryId")]
827    #[serde(alias = "@id")]
828    #[serde(alias = "queryId")]
829    pub query_id: Arc<str>,
830
831    #[serde(rename = "reviewedBy")]
832    #[serde(alias = "@reviewedBy")]
833    #[serde(alias = "reviewedBy")]
834    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
835    pub reviewed_by: Option<String>,
836
837    #[serde(rename = "reviewedByUniqueId")]
838    #[serde(alias = "@reviewedByUniqueId")]
839    #[serde(alias = "reviewedByUniqueId")]
840    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
841    pub reviewed_by_unique_id: Option<String>,
842
843    #[serde(rename = "reviewedByWhen")]
844    #[serde(alias = "@reviewedByWhen")]
845    #[serde(alias = "reviewedByWhen")]
846    #[serde(
847        default,
848        deserialize_with = "deserialize_empty_string_as_none_datetime"
849    )]
850    pub reviewed_by_when: Option<DateTime<Utc>>,
851
852    pub value: Option<Value>,
853    pub answer: Option<Value>,
854}
855
856#[cfg(feature = "python")]
857#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
858#[pyclass(skip_from_py_object)]
859pub struct File {
860    #[serde(rename = "name")]
861    #[serde(alias = "@name")]
862    #[serde(alias = "name")]
863    pub name: Arc<str>,
864
865    #[serde(rename = "fileType")]
866    #[serde(alias = "@type")]
867    #[serde(alias = "fileType")]
868    pub file_type: Arc<str>,
869
870    #[serde(rename = "dataType")]
871    #[serde(alias = "@dataType")]
872    #[serde(alias = "dataType")]
873    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
874    pub data_type: Option<Arc<str>>,
875
876    #[serde(rename = "errorCode")]
877    #[serde(alias = "@errorCode")]
878    #[serde(alias = "errorCode")]
879    pub error_code: Arc<str>,
880
881    #[serde(rename = "whenCreated")]
882    #[serde(alias = "@whenCreated")]
883    #[serde(alias = "whenCreated")]
884    pub when_created: Option<DateTime<Utc>>,
885
886    #[serde(rename = "keepHistory")]
887    #[serde(alias = "@keepHistory")]
888    #[serde(alias = "keepHistory")]
889    pub keep_history: bool,
890
891    #[serde(rename = "fileLocation")]
892    #[serde(alias = "@fileLocation")]
893    #[serde(alias = "fileLocation")]
894    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
895    pub file_location: Option<String>,
896
897    #[serde(rename = "size")]
898    #[serde(alias = "@size")]
899    #[serde(alias = "size")]
900    #[serde(default)]
901    pub size: Option<usize>,
902
903    #[serde(alias = "entry")]
904    pub entries: Option<Arc<Vec<Entry>>>,
905
906    #[serde(alias = "comment")]
907    pub comments: Option<Arc<Vec<Comment>>>,
908
909    #[serde(alias = "query")]
910    pub queries: Option<Arc<Vec<Query>>>,
911
912    #[serde(rename = "downloadHistory")]
913    #[serde(alias = "downloadHistory")]
914    pub download_history: Option<Arc<Vec<Comment>>>,
915}
916
917#[cfg(not(feature = "python"))]
918#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
919pub struct Field {
920    #[serde(rename = "name")]
921    #[serde(alias = "@name")]
922    #[serde(alias = "name")]
923    pub name: Arc<str>,
924
925    #[serde(rename = "fieldType")]
926    #[serde(alias = "@type")]
927    #[serde(alias = "fieldType")]
928    pub field_type: Arc<str>,
929
930    #[serde(rename = "dataType")]
931    #[serde(alias = "@dataType")]
932    #[serde(alias = "dataType")]
933    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
934    pub data_type: Option<Arc<str>>,
935    #[serde(rename = "errorCode")]
936    #[serde(alias = "@errorCode")]
937    #[serde(alias = "errorCode")]
938    pub error_code: Arc<str>,
939    #[serde(rename = "whenCreated")]
940    #[serde(alias = "@whenCreated")]
941    #[serde(alias = "whenCreated")]
942    pub when_created: Option<DateTime<Utc>>,
943    #[serde(rename = "keepHistory")]
944    #[serde(alias = "@keepHistory")]
945    #[serde(alias = "keepHistory")]
946    pub keep_history: bool,
947
948    #[serde(alias = "entry")]
949    pub entries: Option<Arc<Vec<Entry>>>,
950
951    #[serde(alias = "comment")]
952    pub comments: Option<Arc<Vec<Comment>>>,
953
954    #[serde(alias = "query")]
955    pub queries: Option<Arc<Vec<Query>>>,
956}
957
958#[cfg(feature = "python")]
959#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
960#[pyclass(skip_from_py_object)]
961pub struct Field {
962    #[serde(rename = "name")]
963    #[serde(alias = "@name")]
964    #[serde(alias = "name")]
965    pub name: Arc<str>,
966
967    #[serde(rename = "fieldType")]
968    #[serde(alias = "@type")]
969    #[serde(alias = "fieldType")]
970    pub field_type: Arc<str>,
971
972    #[serde(rename = "dataType")]
973    #[serde(alias = "@dataType")]
974    #[serde(alias = "dataType")]
975    #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
976    pub data_type: Option<Arc<str>>,
977
978    #[serde(rename = "errorCode")]
979    #[serde(alias = "@errorCode")]
980    #[serde(alias = "errorCode")]
981    pub error_code: Arc<str>,
982    #[serde(rename = "whenCreated")]
983    #[serde(alias = "@whenCreated")]
984    #[serde(alias = "whenCreated")]
985    pub when_created: Option<DateTime<Utc>>,
986    #[serde(rename = "keepHistory")]
987    #[serde(alias = "@keepHistory")]
988    #[serde(alias = "keepHistory")]
989    pub keep_history: bool,
990
991    #[serde(alias = "entry")]
992    pub entries: Option<Arc<Vec<Entry>>>,
993
994    #[serde(alias = "comment")]
995    pub comments: Option<Arc<Vec<Comment>>>,
996
997    #[serde(alias = "query")]
998    pub queries: Option<Arc<Vec<Query>>>,
999}
1000
1001#[cfg(feature = "python")]
1002#[pymethods]
1003impl Field {
1004    #[getter]
1005    fn name(&self) -> PyResult<String> {
1006        Ok(self.name.to_string())
1007    }
1008
1009    #[getter]
1010    fn field_type(&self) -> PyResult<String> {
1011        Ok(self.field_type.to_string())
1012    }
1013
1014    #[getter]
1015    fn data_type(&self) -> PyResult<Option<String>> {
1016        Ok(self.data_type.as_deref().map(str::to_string))
1017    }
1018
1019    #[getter]
1020    fn error_code(&self) -> PyResult<String> {
1021        Ok(self.error_code.to_string())
1022    }
1023
1024    #[getter]
1025    fn when_created<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1026        self.when_created
1027            .as_ref()
1028            .map(|dt| to_py_datetime(py, dt))
1029            .transpose()
1030    }
1031
1032    #[getter]
1033    fn keep_history(&self) -> PyResult<bool> {
1034        Ok(self.keep_history)
1035    }
1036
1037    #[getter]
1038    fn entries(&self) -> PyResult<Option<Vec<Entry>>> {
1039        Ok(self.entries.as_deref().cloned())
1040    }
1041
1042    #[getter]
1043    fn comments(&self) -> PyResult<Option<Vec<Comment>>> {
1044        Ok(self.comments.as_deref().cloned())
1045    }
1046
1047    #[getter]
1048    fn queries(&self) -> PyResult<Option<Vec<Query>>> {
1049        Ok(self.queries.as_deref().cloned())
1050    }
1051
1052    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1053        let dict = PyDict::new(py);
1054        dict.set_item("name", &*self.name)?;
1055        dict.set_item("field_type", &*self.field_type)?;
1056        dict.set_item("data_type", self.data_type.as_deref())?;
1057        dict.set_item("error_code", &*self.error_code)?;
1058        dict.set_item(
1059            "when_created",
1060            self.when_created
1061                .as_ref()
1062                .map(|dt| to_py_datetime(py, dt))
1063                .transpose()?,
1064        )?;
1065        dict.set_item("keep_history", self.keep_history)?;
1066
1067        let mut entry_dicts = Vec::new();
1068        if let Some(entries) = &self.entries {
1069            for entry in entries.iter() {
1070                let entry_dict = entry.to_dict(py)?;
1071                entry_dicts.push(entry_dict);
1072            }
1073            dict.set_item("entries", entry_dicts)?;
1074        } else {
1075            dict.set_item("entries", py.None())?;
1076        }
1077
1078        let mut comment_dicts = Vec::new();
1079        if let Some(comments) = &self.comments {
1080            for comment in comments.iter() {
1081                let comment_dict = comment.to_dict(py)?;
1082                comment_dicts.push(comment_dict);
1083            }
1084            dict.set_item("comments", comment_dicts)?;
1085        } else {
1086            dict.set_item("comments", py.None())?;
1087        }
1088
1089        let mut queries_dicts = Vec::new();
1090        if let Some(queries) = &self.queries {
1091            for item in queries.iter() {
1092                queries_dicts.push(item.to_dict(py)?);
1093            }
1094            dict.set_item("queries", queries_dicts)?;
1095        } else {
1096            dict.set_item("queries", py.None())?;
1097        }
1098        Ok(dict)
1099    }
1100}
1101
1102#[cfg(not(feature = "python"))]
1103#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1104pub struct Category {
1105    #[serde(rename = "name")]
1106    #[serde(alias = "@name")]
1107    #[serde(alias = "name")]
1108    pub name: Arc<str>,
1109
1110    #[serde(rename = "categoryType")]
1111    #[serde(alias = "@type")]
1112    #[serde(alias = "categoryType")]
1113    pub category_type: Arc<str>,
1114
1115    #[serde(rename = "highestIndex")]
1116    #[serde(alias = "@highestIndex")]
1117    #[serde(alias = "highestIndex")]
1118    pub highest_index: usize,
1119
1120    #[serde(rename = "obfuscated")]
1121    #[serde(alias = "@obfuscated")]
1122    #[serde(alias = "obfuscated")]
1123    #[serde(default)]
1124    pub obfuscated: bool,
1125
1126    #[serde(rename = "overRideHighestIndex")]
1127    #[serde(alias = "@overRideHighestIndex")]
1128    #[serde(alias = "overRideHighestIndex")]
1129    #[serde(default)]
1130    pub over_ride_highest_index: bool,
1131
1132    #[serde(alias = "field")]
1133    pub fields: Option<Arc<Vec<Field>>>,
1134
1135    #[serde(alias = "file")]
1136    pub files: Option<Arc<Vec<File>>>,
1137}
1138
1139#[cfg(feature = "python")]
1140#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1141#[pyclass(skip_from_py_object)]
1142pub struct Category {
1143    #[serde(rename = "name")]
1144    #[serde(alias = "@name")]
1145    #[serde(alias = "name")]
1146    pub name: Arc<str>,
1147
1148    #[serde(rename = "categoryType")]
1149    #[serde(alias = "@type")]
1150    #[serde(alias = "categoryType")]
1151    pub category_type: Arc<str>,
1152
1153    #[serde(rename = "highestIndex")]
1154    #[serde(alias = "@highestIndex")]
1155    #[serde(alias = "highestIndex")]
1156    pub highest_index: usize,
1157
1158    #[serde(rename = "obfuscated")]
1159    #[serde(alias = "@obfuscated")]
1160    #[serde(alias = "obfuscated")]
1161    #[serde(default)]
1162    pub obfuscated: bool,
1163
1164    #[serde(rename = "overRideHighestIndex")]
1165    #[serde(alias = "@overRideHighestIndex")]
1166    #[serde(alias = "overRideHighestIndex")]
1167    #[serde(default)]
1168    pub over_ride_highest_index: bool,
1169
1170    #[serde(alias = "field")]
1171    pub fields: Option<Arc<Vec<Field>>>,
1172
1173    #[serde(alias = "file")]
1174    pub files: Option<Arc<Vec<File>>>,
1175}
1176
1177#[cfg(feature = "python")]
1178#[pymethods]
1179impl Category {
1180    #[getter]
1181    fn name(&self) -> PyResult<String> {
1182        Ok(self.name.to_string())
1183    }
1184
1185    #[getter]
1186    fn category_type(&self) -> PyResult<String> {
1187        Ok(self.category_type.to_string())
1188    }
1189
1190    #[getter]
1191    fn highest_index(&self) -> PyResult<usize> {
1192        Ok(self.highest_index)
1193    }
1194
1195    #[getter]
1196    fn fields(&self) -> PyResult<Option<Vec<Field>>> {
1197        Ok(self.fields.as_deref().cloned())
1198    }
1199
1200    #[getter]
1201    fn files(&self) -> PyResult<Option<Vec<File>>> {
1202        Ok(self.files.as_deref().cloned())
1203    }
1204
1205    #[getter]
1206    fn obfuscated(&self) -> PyResult<bool> {
1207        Ok(self.obfuscated)
1208    }
1209
1210    #[getter]
1211    fn over_ride_highest_index(&self) -> PyResult<bool> {
1212        Ok(self.over_ride_highest_index)
1213    }
1214
1215    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1216        let dict = PyDict::new(py);
1217        dict.set_item("name", &*self.name)?;
1218        dict.set_item("category_type", &*self.category_type)?;
1219        dict.set_item("highest_index", self.highest_index)?;
1220        dict.set_item("obfuscated", self.obfuscated)?;
1221        dict.set_item("over_ride_highest_index", self.over_ride_highest_index)?;
1222
1223        let mut field_dicts = Vec::new();
1224        if let Some(fields) = &self.fields {
1225            for field in fields.iter() {
1226                let field_dict = field.to_dict(py)?;
1227                field_dicts.push(field_dict);
1228            }
1229            dict.set_item("fields", field_dicts)?;
1230        } else {
1231            dict.set_item("fields", py.None())?;
1232        }
1233
1234        let mut files_dicts = Vec::new();
1235        if let Some(files) = &self.files {
1236            for item in files.iter() {
1237                files_dicts.push(item.to_dict(py)?);
1238            }
1239            dict.set_item("files", files_dicts)?;
1240        } else {
1241            dict.set_item("files", py.None())?;
1242        }
1243        Ok(dict)
1244    }
1245}
1246
1247impl Form {
1248    pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
1249        let mut name = "";
1250        let mut last_modified = "";
1251        let mut who_last_modified_name = "";
1252        let mut who_last_modified_role = "";
1253        let mut when_created = "";
1254        let mut has_errors = "";
1255        let mut has_warnings = "";
1256        let mut locked = "";
1257        let mut user = "";
1258        let mut date_time_changed = "";
1259        let mut form_title = "";
1260        let mut form_index = "";
1261        let mut form_group = "";
1262        let mut form_state = "";
1263
1264        visit_attributes(e, |key, attr| match key {
1265            b"name" => name = attr,
1266            b"lastModified" => last_modified = attr,
1267            b"whoLastModifiedName" => who_last_modified_name = attr,
1268            b"whoLastModifiedRole" => who_last_modified_role = attr,
1269            b"whenCreated" => when_created = attr,
1270            b"hasErrors" => has_errors = attr,
1271            b"hasWarnings" => has_warnings = attr,
1272            b"locked" => locked = attr,
1273            b"user" => user = attr,
1274            b"dateTimeChanged" => date_time_changed = attr,
1275            b"formTitle" => form_title = attr,
1276            b"formIndex" => form_index = attr,
1277            b"formGroup" => form_group = attr,
1278            b"formState" => form_state = attr,
1279            _ => {}
1280        })?;
1281
1282        Ok(Form {
1283            name: attribute_string(name),
1284            last_modified: optional_datetime(last_modified),
1285            who_last_modified_name: optional_string(who_last_modified_name),
1286            who_last_modified_role: optional_string(who_last_modified_role),
1287            when_created: when_created.parse().unwrap_or(0),
1288            has_errors: has_errors == "true",
1289            has_warnings: has_warnings == "true",
1290            locked: locked == "true",
1291            user: optional_string(user),
1292            date_time_changed: optional_datetime(date_time_changed),
1293            form_title: attribute_string(form_title),
1294            form_index: form_index.parse().unwrap_or(0),
1295            form_group: optional_string(form_group),
1296            form_state: attribute_string(form_state),
1297            states: None,
1298            lock_states: None,
1299            categories: None,
1300        })
1301    }
1302}
1303
1304#[cfg(not(feature = "python"))]
1305#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1306pub struct State {
1307    #[serde(rename = "value")]
1308    #[serde(alias = "@value")]
1309    #[serde(alias = "value")]
1310    pub value: Arc<str>,
1311    #[serde(rename = "signer")]
1312    #[serde(alias = "@signer")]
1313    #[serde(alias = "signer")]
1314    pub signer: Arc<str>,
1315    #[serde(rename = "signerUniqueId")]
1316    #[serde(alias = "@signerUniqueId")]
1317    #[serde(alias = "signerUniqueId")]
1318    pub signer_unique_id: Arc<str>,
1319
1320    #[serde(rename = "dateSigned")]
1321    #[serde(alias = "@dateSigned")]
1322    #[serde(alias = "dateSigned")]
1323    #[serde(
1324        default,
1325        deserialize_with = "deserialize_empty_string_as_none_datetime"
1326    )]
1327    pub date_signed: Option<DateTime<Utc>>,
1328}
1329
1330#[cfg(feature = "python")]
1331#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1332#[pyclass(skip_from_py_object)]
1333pub struct State {
1334    #[serde(rename = "value")]
1335    #[serde(alias = "@value")]
1336    #[serde(alias = "value")]
1337    pub value: Arc<str>,
1338    #[serde(rename = "signer")]
1339    #[serde(alias = "@signer")]
1340    #[serde(alias = "signer")]
1341    pub signer: Arc<str>,
1342    #[serde(rename = "signerUniqueId")]
1343    #[serde(alias = "@signerUniqueId")]
1344    #[serde(alias = "signerUniqueId")]
1345    pub signer_unique_id: Arc<str>,
1346
1347    #[serde(rename = "dateSigned")]
1348    #[serde(alias = "@dateSigned")]
1349    #[serde(alias = "dateSigned")]
1350    #[serde(
1351        default,
1352        deserialize_with = "deserialize_empty_string_as_none_datetime"
1353    )]
1354    pub date_signed: Option<DateTime<Utc>>,
1355}
1356
1357#[cfg(feature = "python")]
1358#[pymethods]
1359impl State {
1360    #[getter]
1361    fn value(&self) -> PyResult<String> {
1362        Ok(self.value.to_string())
1363    }
1364
1365    #[getter]
1366    fn signer(&self) -> PyResult<String> {
1367        Ok(self.signer.to_string())
1368    }
1369
1370    #[getter]
1371    fn signer_unique_id(&self) -> PyResult<String> {
1372        Ok(self.signer_unique_id.to_string())
1373    }
1374
1375    #[getter]
1376    fn date_signed<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1377        to_py_datetime_option(py, &self.date_signed)
1378    }
1379
1380    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1381        let dict = PyDict::new(py);
1382        dict.set_item("value", &*self.value)?;
1383        dict.set_item("signer", &*self.signer)?;
1384        dict.set_item("signer_unique_id", &*self.signer_unique_id)?;
1385        dict.set_item("date_signed", to_py_datetime_option(py, &self.date_signed)?)?;
1386
1387        Ok(dict)
1388    }
1389}
1390
1391#[cfg(not(feature = "python"))]
1392#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1393pub struct LockState {
1394    #[serde(rename = "locked")]
1395    #[serde(alias = "@locked")]
1396    #[serde(alias = "locked")]
1397    pub locked: bool,
1398
1399    #[serde(rename = "user")]
1400    #[serde(alias = "@user")]
1401    #[serde(alias = "user")]
1402    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1403    pub user: Option<String>,
1404
1405    #[serde(rename = "userUniqueId")]
1406    #[serde(alias = "@userUniqueId")]
1407    #[serde(alias = "userUniqueId")]
1408    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1409    pub user_unique_id: Option<String>,
1410
1411    #[serde(rename = "dateTimeChanged")]
1412    #[serde(alias = "@dateTimeChanged")]
1413    #[serde(alias = "dateTimeChanged")]
1414    #[serde(
1415        default,
1416        deserialize_with = "deserialize_empty_string_as_none_datetime"
1417    )]
1418    pub date_time_changed: Option<DateTime<Utc>>,
1419}
1420
1421#[cfg(feature = "python")]
1422#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1423#[pyclass(skip_from_py_object)]
1424pub struct LockState {
1425    #[serde(rename = "locked")]
1426    #[serde(alias = "@locked")]
1427    #[serde(alias = "locked")]
1428    pub locked: bool,
1429
1430    #[serde(rename = "user")]
1431    #[serde(alias = "@user")]
1432    #[serde(alias = "user")]
1433    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1434    pub user: Option<String>,
1435
1436    #[serde(rename = "userUniqueId")]
1437    #[serde(alias = "@userUniqueId")]
1438    #[serde(alias = "userUniqueId")]
1439    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1440    pub user_unique_id: Option<String>,
1441
1442    #[serde(rename = "dateTimeChanged")]
1443    #[serde(alias = "@dateTimeChanged")]
1444    #[serde(alias = "dateTimeChanged")]
1445    #[serde(
1446        default,
1447        deserialize_with = "deserialize_empty_string_as_none_datetime"
1448    )]
1449    pub date_time_changed: Option<DateTime<Utc>>,
1450}
1451
1452#[cfg(feature = "python")]
1453#[pymethods]
1454impl LockState {
1455    #[getter]
1456    fn locked(&self) -> PyResult<bool> {
1457        Ok(self.locked)
1458    }
1459
1460    #[getter]
1461    fn user(&self) -> PyResult<Option<String>> {
1462        Ok(self.user.clone())
1463    }
1464
1465    #[getter]
1466    fn user_unique_id(&self) -> PyResult<Option<String>> {
1467        Ok(self.user_unique_id.clone())
1468    }
1469
1470    #[getter]
1471    fn date_time_changed<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1472        to_py_datetime_option(py, &self.date_time_changed)
1473    }
1474
1475    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1476        let dict = PyDict::new(py);
1477        dict.set_item("locked", self.locked)?;
1478        dict.set_item("user", &self.user)?;
1479        dict.set_item("user_unique_id", &self.user_unique_id)?;
1480        dict.set_item(
1481            "date_time_changed",
1482            to_py_datetime_option(py, &self.date_time_changed)?,
1483        )?;
1484
1485        Ok(dict)
1486    }
1487}
1488
1489#[cfg(not(feature = "python"))]
1490#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1491pub struct Form {
1492    #[serde(rename = "name")]
1493    #[serde(alias = "@name")]
1494    #[serde(alias = "name")]
1495    pub name: String,
1496
1497    #[serde(rename = "lastModified")]
1498    #[serde(alias = "@lastModified")]
1499    #[serde(alias = "lastModified")]
1500    #[serde(
1501        default,
1502        deserialize_with = "deserialize_empty_string_as_none_datetime"
1503    )]
1504    pub last_modified: Option<DateTime<Utc>>,
1505
1506    #[serde(rename = "whoLastModifiedName")]
1507    #[serde(alias = "@whoLastModifiedName")]
1508    #[serde(alias = "whoLastModifiedName")]
1509    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1510    pub who_last_modified_name: Option<String>,
1511
1512    #[serde(rename = "whoLastModifiedRole")]
1513    #[serde(alias = "@whoLastModifiedRole")]
1514    #[serde(alias = "whoLastModifiedRole")]
1515    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1516    pub who_last_modified_role: Option<String>,
1517
1518    #[serde(rename = "whenCreated")]
1519    #[serde(alias = "@whenCreated")]
1520    #[serde(alias = "whenCreated")]
1521    pub when_created: usize,
1522    #[serde(rename = "hasErrors")]
1523    #[serde(alias = "@hasErrors")]
1524    #[serde(alias = "hasErrors")]
1525    pub has_errors: bool,
1526    #[serde(rename = "hasWarnings")]
1527    #[serde(alias = "@hasWarnings")]
1528    #[serde(alias = "hasWarnings")]
1529    pub has_warnings: bool,
1530    #[serde(rename = "locked")]
1531    #[serde(alias = "@locked")]
1532    #[serde(alias = "locked")]
1533    pub locked: bool,
1534
1535    #[serde(rename = "user")]
1536    #[serde(alias = "@user")]
1537    #[serde(alias = "user")]
1538    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1539    pub user: Option<String>,
1540
1541    #[serde(rename = "dateTimeChanged")]
1542    #[serde(alias = "@dateTimeChanged")]
1543    #[serde(alias = "dateTimeChanged")]
1544    #[serde(
1545        default,
1546        deserialize_with = "deserialize_empty_string_as_none_datetime"
1547    )]
1548    pub date_time_changed: Option<DateTime<Utc>>,
1549
1550    #[serde(rename = "formTitle")]
1551    #[serde(alias = "@formTitle")]
1552    #[serde(alias = "formTitle")]
1553    pub form_title: String,
1554    #[serde(rename = "formIndex")]
1555    #[serde(alias = "@formIndex")]
1556    #[serde(alias = "formIndex")]
1557    pub form_index: usize,
1558
1559    #[serde(rename = "formGroup")]
1560    #[serde(alias = "@formGroup")]
1561    #[serde(alias = "formGroup")]
1562    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1563    pub form_group: Option<String>,
1564
1565    #[serde(rename = "formState")]
1566    #[serde(alias = "@formState")]
1567    #[serde(alias = "formState")]
1568    pub form_state: String,
1569
1570    #[serde(alias = "state")]
1571    pub states: Option<Arc<Vec<State>>>,
1572
1573    #[serde(alias = "lockState")]
1574    pub lock_states: Option<Arc<Vec<LockState>>>,
1575
1576    #[serde(alias = "category")]
1577    pub categories: Option<Arc<Vec<Category>>>,
1578}
1579
1580#[cfg(feature = "python")]
1581#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1582#[pyclass(skip_from_py_object)]
1583pub struct Form {
1584    #[serde(rename = "name")]
1585    #[serde(alias = "@name")]
1586    #[serde(alias = "name")]
1587    pub name: String,
1588
1589    #[serde(rename = "lastModified")]
1590    #[serde(alias = "@lastModified")]
1591    #[serde(alias = "lastModified")]
1592    #[serde(
1593        default,
1594        deserialize_with = "deserialize_empty_string_as_none_datetime"
1595    )]
1596    pub last_modified: Option<DateTime<Utc>>,
1597
1598    #[serde(rename = "whoLastModifiedName")]
1599    #[serde(alias = "@whoLastModifiedName")]
1600    #[serde(alias = "whoLastModifiedName")]
1601    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1602    pub who_last_modified_name: Option<String>,
1603
1604    #[serde(rename = "whoLastModifiedRole")]
1605    #[serde(alias = "@whoLastModifiedRole")]
1606    #[serde(alias = "whoLastModifiedRole")]
1607    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1608    pub who_last_modified_role: Option<String>,
1609
1610    #[serde(rename = "whenCreated")]
1611    #[serde(alias = "@whenCreated")]
1612    #[serde(alias = "whenCreated")]
1613    pub when_created: usize,
1614    #[serde(rename = "hasErrors")]
1615    #[serde(alias = "@hasErrors")]
1616    #[serde(alias = "hasErrors")]
1617    pub has_errors: bool,
1618    #[serde(rename = "hasWarnings")]
1619    #[serde(alias = "@hasWarnings")]
1620    #[serde(alias = "hasWarnings")]
1621    pub has_warnings: bool,
1622    #[serde(rename = "locked")]
1623    #[serde(alias = "@locked")]
1624    #[serde(alias = "locked")]
1625    pub locked: bool,
1626
1627    #[serde(rename = "user")]
1628    #[serde(alias = "@user")]
1629    #[serde(alias = "user")]
1630    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1631    pub user: Option<String>,
1632
1633    #[serde(rename = "dateTimeChanged")]
1634    #[serde(alias = "@dateTimeChanged")]
1635    #[serde(alias = "dateTimeChanged")]
1636    #[serde(
1637        default,
1638        deserialize_with = "deserialize_empty_string_as_none_datetime"
1639    )]
1640    pub date_time_changed: Option<DateTime<Utc>>,
1641
1642    #[serde(rename = "formTitle")]
1643    #[serde(alias = "@formTitle")]
1644    #[serde(alias = "formTitle")]
1645    pub form_title: String,
1646    #[serde(rename = "formIndex")]
1647    #[serde(alias = "@formIndex")]
1648    #[serde(alias = "formIndex")]
1649    pub form_index: usize,
1650
1651    #[serde(rename = "formGroup")]
1652    #[serde(alias = "@formGroup")]
1653    #[serde(alias = "formGroup")]
1654    #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1655    pub form_group: Option<String>,
1656
1657    #[serde(rename = "formState")]
1658    #[serde(alias = "@formState")]
1659    #[serde(alias = "formState")]
1660    pub form_state: String,
1661
1662    #[serde(alias = "state")]
1663    pub states: Option<Arc<Vec<State>>>,
1664
1665    #[serde(alias = "lockState")]
1666    pub lock_states: Option<Arc<Vec<LockState>>>,
1667
1668    #[serde(alias = "category")]
1669    pub categories: Option<Arc<Vec<Category>>>,
1670}
1671
1672#[cfg(feature = "python")]
1673#[pymethods]
1674impl Form {
1675    #[getter]
1676    fn name(&self) -> PyResult<String> {
1677        Ok(self.name.clone())
1678    }
1679
1680    #[getter]
1681    fn last_modified<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1682        to_py_datetime_option(py, &self.last_modified)
1683    }
1684
1685    #[getter]
1686    fn who_last_modified_name(&self) -> PyResult<Option<String>> {
1687        Ok(self.who_last_modified_name.clone())
1688    }
1689
1690    #[getter]
1691    fn who_last_modified_role(&self) -> PyResult<Option<String>> {
1692        Ok(self.who_last_modified_role.clone())
1693    }
1694
1695    #[getter]
1696    fn when_created(&self) -> PyResult<usize> {
1697        Ok(self.when_created)
1698    }
1699
1700    #[getter]
1701    fn has_errors(&self) -> PyResult<bool> {
1702        Ok(self.has_errors)
1703    }
1704
1705    #[getter]
1706    fn has_warnings(&self) -> PyResult<bool> {
1707        Ok(self.has_warnings)
1708    }
1709
1710    #[getter]
1711    fn locked(&self) -> PyResult<bool> {
1712        Ok(self.locked)
1713    }
1714
1715    #[getter]
1716    fn user(&self) -> PyResult<Option<String>> {
1717        Ok(self.user.clone())
1718    }
1719
1720    #[getter]
1721    fn date_time_changed<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1722        to_py_datetime_option(py, &self.date_time_changed)
1723    }
1724
1725    #[getter]
1726    fn form_title(&self) -> PyResult<String> {
1727        Ok(self.form_title.clone())
1728    }
1729
1730    #[getter]
1731    fn form_index(&self) -> PyResult<usize> {
1732        Ok(self.form_index)
1733    }
1734
1735    #[getter]
1736    fn form_group(&self) -> PyResult<Option<String>> {
1737        Ok(self.form_group.clone())
1738    }
1739
1740    #[getter]
1741    fn form_state(&self) -> PyResult<String> {
1742        Ok(self.form_state.clone())
1743    }
1744
1745    #[getter]
1746    fn states(&self) -> PyResult<Option<Vec<State>>> {
1747        Ok(self.states.as_deref().cloned())
1748    }
1749
1750    #[getter]
1751    fn lock_states(&self) -> PyResult<Option<Vec<LockState>>> {
1752        Ok(self.lock_states.as_deref().cloned())
1753    }
1754
1755    #[getter]
1756    fn categories(&self) -> PyResult<Option<Vec<Category>>> {
1757        Ok(self.categories.as_deref().cloned())
1758    }
1759
1760    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1761        let dict = PyDict::new(py);
1762        dict.set_item("name", &self.name)?;
1763        dict.set_item(
1764            "last_modified",
1765            to_py_datetime_option(py, &self.last_modified)?,
1766        )?;
1767        dict.set_item("who_last_modified_name", &self.who_last_modified_name)?;
1768        dict.set_item("who_last_modified_role", &self.who_last_modified_role)?;
1769        dict.set_item("when_created", self.when_created)?;
1770        dict.set_item("has_errors", self.has_errors)?;
1771        dict.set_item("has_warnings", self.has_warnings)?;
1772        dict.set_item("locked", self.locked)?;
1773        dict.set_item("user", &self.user)?;
1774        dict.set_item(
1775            "date_time_changed",
1776            to_py_datetime_option(py, &self.date_time_changed)?,
1777        )?;
1778        dict.set_item("form_title", &self.form_title)?;
1779        dict.set_item("form_index", self.form_index)?;
1780        dict.set_item("form_group", &self.form_group)?;
1781        dict.set_item("form_state", &self.form_state)?;
1782
1783        let mut state_dicts = Vec::new();
1784        if let Some(states) = &self.states {
1785            for state in states.iter() {
1786                let state_dict = state.to_dict(py)?;
1787                state_dicts.push(state_dict);
1788            }
1789            dict.set_item("states", state_dicts)?;
1790        } else {
1791            dict.set_item("states", py.None())?;
1792        }
1793
1794        let mut lock_state_dicts = Vec::new();
1795        if let Some(lock_states) = &self.lock_states {
1796            for lock_state in lock_states.iter() {
1797                let lock_state_dict = lock_state.to_dict(py)?;
1798                lock_state_dicts.push(lock_state_dict);
1799            }
1800            dict.set_item("lock_states", lock_state_dicts)?;
1801        } else {
1802            dict.set_item("lock_states", py.None())?;
1803        }
1804
1805        if let Some(categories) = &self.categories {
1806            let mut category_dicts = Vec::new();
1807            for category in categories.iter() {
1808                let category_dict = category.to_dict(py)?;
1809                category_dicts.push(category_dict);
1810            }
1811            dict.set_item("categories", category_dicts)?;
1812        } else {
1813            dict.set_item("categories", py.None())?;
1814        }
1815
1816        Ok(dict)
1817    }
1818}
1819
1820impl State {
1821    pub(crate) fn from_attributes(
1822        e: &BytesStart<'_>,
1823        interner: &mut Interner,
1824    ) -> Result<Self, crate::errors::Error> {
1825        let mut value = "";
1826        let mut signer = "";
1827        let mut signer_unique_id = "";
1828        let mut date_signed = "";
1829
1830        visit_attributes(e, |key, attr| match key {
1831            b"value" => value = attr,
1832            b"signer" => signer = attr,
1833            b"signerUniqueId" => signer_unique_id = attr,
1834            b"dateSigned" => date_signed = attr,
1835            _ => {}
1836        })?;
1837
1838        Ok(State {
1839            value: interner.intern(value),
1840            signer: interner.intern(signer),
1841            signer_unique_id: interner.intern(signer_unique_id),
1842            date_signed: optional_datetime(date_signed),
1843        })
1844    }
1845}
1846
1847impl LockState {
1848    pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
1849        let mut locked = "";
1850        let mut user = "";
1851        let mut user_unique_id = "";
1852        let mut date_time_changed = "";
1853
1854        visit_attributes(e, |key, attr| match key {
1855            b"locked" => locked = attr,
1856            b"user" => user = attr,
1857            b"userUniqueId" => user_unique_id = attr,
1858            b"dateTimeChanged" => date_time_changed = attr,
1859            _ => {}
1860        })?;
1861
1862        Ok(LockState {
1863            locked: locked == "true",
1864            user: optional_string(user),
1865            user_unique_id: optional_string(user_unique_id),
1866            date_time_changed: optional_datetime(date_time_changed),
1867        })
1868    }
1869}
1870
1871impl Category {
1872    pub(crate) fn from_attributes(
1873        e: &BytesStart<'_>,
1874        interner: &mut Interner,
1875    ) -> Result<Self, crate::errors::Error> {
1876        let mut name = "";
1877        let mut category_type = "";
1878        let mut highest_index = "";
1879        let mut obfuscated = "";
1880        let mut over_ride_highest_index = "";
1881
1882        visit_attributes(e, |key, attr| match key {
1883            b"name" => name = attr,
1884            b"type" => category_type = attr,
1885            b"highestIndex" => highest_index = attr,
1886            b"obfuscated" => obfuscated = attr,
1887            b"overRideHighestIndex" => over_ride_highest_index = attr,
1888            _ => {}
1889        })?;
1890
1891        Ok(Category {
1892            name: interner.intern(name),
1893            category_type: interner.intern(category_type),
1894            highest_index: highest_index.parse().unwrap_or(0),
1895            obfuscated: obfuscated == "true",
1896            over_ride_highest_index: over_ride_highest_index == "true",
1897            fields: None,
1898            files: None,
1899        })
1900    }
1901}
1902
1903impl Field {
1904    pub(crate) fn from_attributes(
1905        e: &BytesStart<'_>,
1906        interner: &mut Interner,
1907    ) -> Result<Self, crate::errors::Error> {
1908        let mut name = "";
1909        let mut field_type = "";
1910        let mut data_type = "";
1911        let mut error_code = "";
1912        let mut when_created = "";
1913        let mut keep_history = "";
1914
1915        visit_attributes(e, |key, attr| match key {
1916            b"name" => name = attr,
1917            b"type" => field_type = attr,
1918            b"dataType" => data_type = attr,
1919            b"errorCode" => error_code = attr,
1920            b"whenCreated" => when_created = attr,
1921            b"keepHistory" => keep_history = attr,
1922            _ => {}
1923        })?;
1924
1925        Ok(Field {
1926            name: interner.intern(name),
1927            field_type: interner.intern(field_type),
1928            data_type: interner.intern_optional(data_type),
1929            error_code: interner.intern(error_code),
1930            when_created: checked_datetime(when_created)?,
1931            keep_history: keep_history == "true",
1932            entries: None,
1933            comments: None,
1934            queries: None,
1935        })
1936    }
1937}
1938
1939impl Entry {
1940    pub(crate) fn from_attributes(
1941        e: &BytesStart<'_>,
1942        interner: &mut Interner,
1943    ) -> Result<Self, crate::errors::Error> {
1944        let mut id: Option<&str> = None;
1945        let mut entry_id: Option<&str> = None;
1946        let mut reviewed_by = "";
1947        let mut reviewed_by_unique_id = "";
1948        let mut reviewed_by_when = "";
1949
1950        visit_attributes(e, |key, attr| match key {
1951            b"id" => id = Some(attr),
1952            b"entryId" => entry_id = Some(attr),
1953            b"reviewedBy" => reviewed_by = attr,
1954            b"reviewedByUniqueId" => reviewed_by_unique_id = attr,
1955            b"reviewedByWhen" => reviewed_by_when = attr,
1956            _ => {}
1957        })?;
1958
1959        Ok(Entry {
1960            entry_id: interner.intern(id.or(entry_id).unwrap_or_default()),
1961            reviewed_by: optional_string(reviewed_by),
1962            reviewed_by_unique_id: optional_string(reviewed_by_unique_id),
1963            reviewed_by_when: optional_datetime(reviewed_by_when),
1964            value: None,
1965            reason: None,
1966        })
1967    }
1968}
1969
1970impl Value {
1971    pub(crate) fn from_attributes(
1972        e: &BytesStart<'_>,
1973        interner: &mut Interner,
1974    ) -> Result<Self, crate::errors::Error> {
1975        let mut by = "";
1976        let mut by_unique_id = "";
1977        let mut role = "";
1978        let mut when = "";
1979
1980        visit_attributes(e, |key, attr| match key {
1981            b"by" => by = attr,
1982            b"byUniqueId" => by_unique_id = attr,
1983            b"role" => role = attr,
1984            b"when" => when = attr,
1985            _ => {}
1986        })?;
1987
1988        Ok(Value {
1989            by: interner.intern(by),
1990            by_unique_id: interner.intern_optional(by_unique_id),
1991            role: interner.intern(role),
1992            when: checked_datetime(when)?,
1993            value: String::new(),
1994        })
1995    }
1996}
1997
1998impl Reason {
1999    pub(crate) fn from_attributes(
2000        e: &BytesStart<'_>,
2001        interner: &mut Interner,
2002    ) -> Result<Self, crate::errors::Error> {
2003        let mut by = "";
2004        let mut by_unique_id = "";
2005        let mut role = "";
2006        let mut when = "";
2007
2008        visit_attributes(e, |key, attr| match key {
2009            b"by" => by = attr,
2010            b"byUniqueId" => by_unique_id = attr,
2011            b"role" => role = attr,
2012            b"when" => when = attr,
2013            _ => {}
2014        })?;
2015
2016        Ok(Reason {
2017            by: interner.intern(by),
2018            by_unique_id: interner.intern_optional(by_unique_id),
2019            role: interner.intern(role),
2020            when: checked_datetime(when)?,
2021            value: String::new(),
2022        })
2023    }
2024}
2025
2026impl Export {
2027    pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
2028        let mut date = "";
2029        let mut created_by = "";
2030        let mut role = "";
2031        let mut number_subjects_processed = "";
2032        let mut page_number = "";
2033
2034        visit_attributes(e, |key, attr| match key {
2035            b"date" => date = attr,
2036            b"createdBy" => created_by = attr,
2037            b"role" => role = attr,
2038            b"numberSubjectsProcessed" => number_subjects_processed = attr,
2039            b"pageNumber" => page_number = attr,
2040            _ => {}
2041        })?;
2042
2043        Ok(Export {
2044            date: optional_datetime(date),
2045            created_by: optional_string(created_by),
2046            role: optional_string(role),
2047            number_subjects_processed: number_subjects_processed.parse().ok(),
2048            page_number: optional_string(page_number),
2049        })
2050    }
2051}
2052
2053#[cfg(feature = "python")]
2054#[pymethods]
2055impl Export {
2056    #[getter]
2057    fn date<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
2058        to_py_datetime_option(py, &self.date)
2059    }
2060
2061    #[getter]
2062    fn created_by(&self) -> PyResult<Option<String>> {
2063        Ok(self.created_by.clone())
2064    }
2065
2066    #[getter]
2067    fn role(&self) -> PyResult<Option<String>> {
2068        Ok(self.role.clone())
2069    }
2070
2071    #[getter]
2072    fn number_subjects_processed(&self) -> PyResult<Option<usize>> {
2073        Ok(self.number_subjects_processed)
2074    }
2075
2076    #[getter]
2077    fn page_number(&self) -> PyResult<Option<String>> {
2078        Ok(self.page_number.clone())
2079    }
2080
2081    pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
2082        let dict = PyDict::new(py);
2083        dict.set_item("date", to_py_datetime_option(py, &self.date)?)?;
2084        dict.set_item("created_by", &self.created_by)?;
2085        dict.set_item("role", &self.role)?;
2086        dict.set_item("number_subjects_processed", self.number_subjects_processed)?;
2087        dict.set_item("page_number", &self.page_number)?;
2088
2089        Ok(dict)
2090    }
2091}
2092
2093impl Query {
2094    pub(crate) fn from_attributes(
2095        e: &BytesStart<'_>,
2096        interner: &mut Interner,
2097    ) -> Result<Self, crate::errors::Error> {
2098        let mut id: Option<&str> = None;
2099        let mut query_id: Option<&str> = None;
2100        let mut reviewed_by = "";
2101        let mut reviewed_by_unique_id = "";
2102        let mut reviewed_by_when = "";
2103
2104        visit_attributes(e, |key, attr| match key {
2105            b"id" => id = Some(attr),
2106            b"queryId" => query_id = Some(attr),
2107            b"reviewedBy" => reviewed_by = attr,
2108            b"reviewedByUniqueId" => reviewed_by_unique_id = attr,
2109            b"reviewedByWhen" => reviewed_by_when = attr,
2110            _ => {}
2111        })?;
2112
2113        Ok(Query {
2114            query_id: interner.intern(id.or(query_id).unwrap_or_default()),
2115            reviewed_by: optional_string(reviewed_by),
2116            reviewed_by_unique_id: optional_string(reviewed_by_unique_id),
2117            reviewed_by_when: optional_datetime(reviewed_by_when),
2118            value: None,
2119            answer: None,
2120        })
2121    }
2122}
2123
2124impl File {
2125    pub(crate) fn from_attributes(
2126        e: &BytesStart<'_>,
2127        interner: &mut Interner,
2128    ) -> Result<Self, crate::errors::Error> {
2129        let mut name = "";
2130        let mut file_type = "";
2131        let mut data_type = "";
2132        let mut error_code = "";
2133        let mut when_created = "";
2134        let mut keep_history = "";
2135        let mut file_location = "";
2136        let mut size = "";
2137
2138        visit_attributes(e, |key, attr| match key {
2139            b"name" => name = attr,
2140            b"type" => file_type = attr,
2141            b"dataType" => data_type = attr,
2142            b"errorCode" => error_code = attr,
2143            b"whenCreated" => when_created = attr,
2144            b"keepHistory" => keep_history = attr,
2145            b"fileLocation" => file_location = attr,
2146            b"size" => size = attr,
2147            _ => {}
2148        })?;
2149
2150        Ok(File {
2151            name: interner.intern(name),
2152            file_type: interner.intern(file_type),
2153            data_type: interner.intern_optional(data_type),
2154            error_code: interner.intern(error_code),
2155            when_created: checked_datetime(when_created)?,
2156            keep_history: keep_history == "true",
2157            file_location: optional_string(file_location),
2158            size: size.parse().ok(),
2159            entries: None,
2160            comments: None,
2161            queries: None,
2162            download_history: None,
2163        })
2164    }
2165}
2166
2167impl Comment {
2168    pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
2169        let mut comment_id = "";
2170        let mut reviewed_by = "";
2171        let mut reviewed_by_unique_id = "";
2172        let mut reviewed_by_when = "";
2173
2174        visit_attributes(e, |key, attr| match key {
2175            b"id" => comment_id = attr,
2176            b"reviewedBy" => reviewed_by = attr,
2177            b"reviewedByUniqueId" => reviewed_by_unique_id = attr,
2178            b"reviewedByWhen" => reviewed_by_when = attr,
2179            _ => {}
2180        })?;
2181
2182        Ok(Comment {
2183            comment_id: attribute_string(comment_id),
2184            reviewed_by: optional_string(reviewed_by),
2185            reviewed_by_unique_id: optional_string(reviewed_by_unique_id),
2186            reviewed_by_when: optional_datetime(reviewed_by_when),
2187            value: None,
2188        })
2189    }
2190}