signalk/
definitions.rs

1use crate::definitions::V2NumberValue::Int;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use time::format_description::well_known::Rfc3339;
5use time::OffsetDateTime;
6
7#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
8pub struct V1CommonValueFields {
9    pub timestamp: String,
10    #[serde(rename = "$source")]
11    pub source: String,
12    #[serde(rename = "_attr")]
13    pub attr: Option<V1Attr>,
14    pub meta: Option<V1Meta>,
15    pub pgn: Option<i64>,
16    pub sentence: Option<String>,
17}
18
19impl V1CommonValueFields {
20    pub fn builder() -> V1CommonValueFieldsBuilder {
21        V1CommonValueFieldsBuilder::default()
22    }
23}
24
25#[derive(Default)]
26pub struct V1CommonValueFieldsBuilder {
27    timestamp: String,
28    source: String,
29    attr: Option<V1Attr>,
30    meta: Option<V1Meta>,
31    pgn: Option<i64>,
32    sentence: Option<String>,
33}
34
35impl V1CommonValueFieldsBuilder {
36    pub fn timestamp(mut self, value: String) -> V1CommonValueFieldsBuilder {
37        self.timestamp = value;
38        self
39    }
40    pub fn source(mut self, value: String) -> V1CommonValueFieldsBuilder {
41        self.source = value;
42        self
43    }
44    pub fn attr(mut self, value: V1Attr) -> V1CommonValueFieldsBuilder {
45        self.attr = Some(value);
46        self
47    }
48    pub fn meta(mut self, value: V1Meta) -> V1CommonValueFieldsBuilder {
49        self.meta = Some(value);
50        self
51    }
52    pub fn pgn(mut self, value: i64) -> V1CommonValueFieldsBuilder {
53        self.pgn = Some(value);
54        self
55    }
56    pub fn sentence(mut self, value: String) -> V1CommonValueFieldsBuilder {
57        self.sentence = Some(value);
58        self
59    }
60    pub fn build(self) -> V1CommonValueFields {
61        V1CommonValueFields {
62            timestamp: self.timestamp,
63            source: self.source,
64            attr: self.attr,
65            meta: self.meta,
66            pgn: self.pgn,
67            sentence: self.sentence,
68        }
69    }
70}
71
72pub trait F64Compatible {
73    fn as_f64(&self) -> Option<f64>;
74}
75
76#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
77#[serde(untagged)]
78pub enum V2NumberValue {
79    ExpandedFloat(V2NumberExpandedFloatValue),
80    Float(f64),
81    Int(i64),
82}
83
84impl V2NumberValue {
85    pub fn from_value(value: &Value) -> Option<Self> {
86        if value.is_null() {
87            None
88        } else {
89            let ship_type_result: Result<Self, serde_json::Error> =
90                serde_json::from_value(value.clone());
91            if let Ok(ship_type_value) = ship_type_result {
92                Some(ship_type_value)
93            } else {
94                None
95            }
96        }
97    }
98}
99impl F64Compatible for V2NumberValue {
100    fn as_f64(&self) -> Option<f64> {
101        match self {
102            V2NumberValue::ExpandedFloat(v) => v.value,
103            V2NumberValue::Float(v) => Some(*v),
104            Int(v) => Some(*v as f64),
105        }
106    }
107}
108
109#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
110pub struct V2NumberExpandedFloatValue {
111    pub value: Option<f64>,
112    #[serde(flatten)]
113    pub common_value_fields: Option<V1CommonValueFields>,
114}
115
116impl Default for V2NumberValue {
117    fn default() -> Self {
118        Int(i64::default())
119    }
120}
121
122#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
123pub struct V1NumberValue {
124    pub value: Option<f64>,
125    pub timestamp: String,
126    #[serde(rename = "$source")]
127    pub source: String,
128    pub pgn: Option<f64>,
129    pub sentence: Option<String>,
130    // TODO: Add support for meta values
131}
132
133impl V1NumberValue {
134    pub fn builder() -> V1NumberValueBuilder {
135        V1NumberValueBuilder::default()
136    }
137
138    pub fn from_value(value: &Value) -> Option<V1NumberValue> {
139        if value.is_null() {
140            None
141        } else {
142            let type_result: Result<V1NumberValue, serde_json::Error> =
143                serde_json::from_value(value.clone());
144            if let Ok(type_value) = type_result {
145                Some(type_value)
146            } else {
147                None
148            }
149        }
150    }
151}
152
153impl F64Compatible for V1NumberValue {
154    fn as_f64(&self) -> Option<f64> {
155        self.value
156    }
157}
158
159#[derive(Default)]
160pub struct V1NumberValueBuilder {
161    pub value: Option<f64>,
162    pub timestamp: String,
163    pub source: String,
164    pub pgn: Option<f64>,
165    pub sentence: Option<String>,
166}
167
168impl V1NumberValueBuilder {
169    pub fn json_value(mut self, value: &serde_json::Value) -> V1NumberValueBuilder {
170        if let Some(f64_value) = value.as_f64() {
171            self.value = Some(f64_value);
172        } else {
173            self.value = None;
174        }
175        self
176    }
177    pub fn value(mut self, value: f64) -> V1NumberValueBuilder {
178        self.value = Some(value);
179        self
180    }
181    pub fn timestamp(mut self, timestamp: String) -> V1NumberValueBuilder {
182        self.timestamp = timestamp;
183        self
184    }
185    pub fn source(mut self, source: String) -> V1NumberValueBuilder {
186        self.source = source;
187        self
188    }
189    pub fn pgn(mut self, pgn: f64) -> V1NumberValueBuilder {
190        self.pgn = Some(pgn);
191        self
192    }
193    pub fn sentence(mut self, sentence: String) -> V1NumberValueBuilder {
194        self.sentence = Some(sentence);
195        self
196    }
197    pub fn build(self) -> V1NumberValue {
198        V1NumberValue {
199            value: self.value,
200            timestamp: self.timestamp,
201            source: self.source,
202            pgn: self.pgn,
203            sentence: self.sentence,
204        }
205    }
206}
207
208#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
209#[serde(rename_all = "camelCase")]
210pub struct V1Meta {
211    pub description: String,
212    pub display_name: Option<String>,
213    pub long_name: Option<String>,
214    pub short_name: Option<String>,
215    #[serde(rename = "enum")]
216    pub enum_: Option<Vec<String>>,
217    pub properties: Option<V1MetaProperties>,
218    pub gauge_type: Option<String>,
219    pub display_scale: Option<V1MetaDisplayScale>,
220    pub units: Option<String>,
221    pub timeout: Option<f64>,
222    pub alert_method: Option<Vec<String>>,
223    pub warn_method: Option<Vec<String>>,
224    pub alarm_method: Option<Vec<String>>,
225    pub emergency_method: Option<Vec<String>>,
226    pub zones: Option<Vec<V1MetaZone>>,
227}
228
229impl V1Meta {
230    pub fn builder() -> V1MetaBuilder {
231        V1MetaBuilder::default()
232    }
233}
234
235#[derive(Default)]
236pub struct V1MetaBuilder {
237    description: String,
238    display_name: Option<String>,
239    long_name: Option<String>,
240    short_name: Option<String>,
241    enum_: Option<Vec<String>>,
242    properties: Option<V1MetaProperties>,
243    gauge_type: Option<String>,
244    display_scale: Option<V1MetaDisplayScale>,
245    units: Option<String>,
246    timeout: Option<f64>,
247    alert_method: Option<Vec<String>>,
248    warn_method: Option<Vec<String>>,
249    alarm_method: Option<Vec<String>>,
250    emergency_method: Option<Vec<String>>,
251    zones: Option<Vec<V1MetaZone>>,
252}
253
254impl V1MetaBuilder {
255    pub fn description(mut self, value: String) -> V1MetaBuilder {
256        self.description = value;
257        self
258    }
259    pub fn display_name(mut self, value: String) -> V1MetaBuilder {
260        self.display_name = Some(value);
261        self
262    }
263    pub fn long_name(mut self, value: String) -> V1MetaBuilder {
264        self.long_name = Some(value);
265        self
266    }
267    pub fn short_name(mut self, value: String) -> V1MetaBuilder {
268        self.short_name = Some(value);
269        self
270    }
271    pub fn enum_(mut self, value: String) -> V1MetaBuilder {
272        if self.enum_.is_none() {
273            self.enum_ = Some(Vec::new());
274        }
275        if let Some(ref mut x) = self.enum_ {
276            x.push(value);
277        }
278        self
279    }
280    pub fn properties(mut self, value: V1MetaProperties) -> V1MetaBuilder {
281        self.properties = Some(value);
282        self
283    }
284    pub fn gauge_type(mut self, value: String) -> V1MetaBuilder {
285        self.gauge_type = Some(value);
286        self
287    }
288    pub fn display_scale(mut self, value: V1MetaDisplayScale) -> V1MetaBuilder {
289        self.display_scale = Some(value);
290        self
291    }
292    pub fn units(mut self, value: String) -> V1MetaBuilder {
293        self.units = Some(value);
294        self
295    }
296    pub fn timeout(mut self, value: f64) -> V1MetaBuilder {
297        self.timeout = Some(value);
298        self
299    }
300    pub fn alert_method(mut self, value: String) -> V1MetaBuilder {
301        if self.alert_method.is_none() {
302            self.alert_method = Some(Vec::new());
303        }
304        if let Some(ref mut x) = self.alert_method {
305            x.push(value);
306        }
307        self
308    }
309    pub fn warn_method(mut self, value: String) -> V1MetaBuilder {
310        if self.warn_method.is_none() {
311            self.warn_method = Some(Vec::new());
312        }
313        if let Some(ref mut x) = self.warn_method {
314            x.push(value);
315        }
316        self
317    }
318    pub fn alarm_method(mut self, value: String) -> V1MetaBuilder {
319        if self.alarm_method.is_none() {
320            self.alarm_method = Some(Vec::new());
321        }
322        if let Some(ref mut x) = self.alarm_method {
323            x.push(value);
324        }
325        self
326    }
327    pub fn emergency_method(mut self, value: String) -> V1MetaBuilder {
328        if self.emergency_method.is_none() {
329            self.emergency_method = Some(Vec::new());
330        }
331        if let Some(ref mut x) = self.emergency_method {
332            x.push(value);
333        }
334        self
335    }
336    pub fn zones(mut self, value: V1MetaZone) -> V1MetaBuilder {
337        if self.zones.is_none() {
338            self.zones = Some(Vec::new());
339        }
340        if let Some(ref mut x) = self.zones {
341            x.push(value);
342        }
343        self
344    }
345    pub fn build(self) -> V1Meta {
346        V1Meta {
347            description: self.description,
348            display_name: self.display_name,
349            long_name: self.long_name,
350            short_name: self.short_name,
351            enum_: self.enum_,
352            properties: self.properties,
353            gauge_type: self.gauge_type,
354            display_scale: self.display_scale,
355            units: self.units,
356            timeout: self.timeout,
357            alert_method: self.alert_method,
358            warn_method: self.warn_method,
359            alarm_method: self.alarm_method,
360            emergency_method: self.emergency_method,
361            zones: self.zones,
362        }
363    }
364}
365
366#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
367#[serde(rename_all = "camelCase")]
368pub struct V1MetaProperties {
369    pub properties: Option<String>,
370    pub title: Option<String>,
371    pub description: Option<String>,
372    pub units: Option<String>,
373    pub example: Option<Value>,
374}
375
376impl V1MetaProperties {
377    pub fn builder() -> V1MetaPropertiesBuilder {
378        V1MetaPropertiesBuilder::default()
379    }
380}
381
382#[derive(Default)]
383pub struct V1MetaPropertiesBuilder {
384    properties: Option<String>,
385    title: Option<String>,
386    description: Option<String>,
387    units: Option<String>,
388    example: Option<Value>,
389}
390
391impl V1MetaPropertiesBuilder {
392    pub fn properties(mut self, value: String) -> V1MetaPropertiesBuilder {
393        self.properties = Some(value);
394        self
395    }
396    pub fn title(mut self, value: String) -> V1MetaPropertiesBuilder {
397        self.title = Some(value);
398        self
399    }
400    pub fn description(mut self, value: String) -> V1MetaPropertiesBuilder {
401        self.description = Some(value);
402        self
403    }
404    pub fn units(mut self, value: String) -> V1MetaPropertiesBuilder {
405        self.units = Some(value);
406        self
407    }
408    pub fn example(mut self, value: Value) -> V1MetaPropertiesBuilder {
409        self.example = Some(value);
410        self
411    }
412
413    pub fn build(self) -> V1MetaProperties {
414        V1MetaProperties {
415            properties: self.properties,
416            title: self.title,
417            description: self.description,
418            units: self.units,
419            example: self.example,
420        }
421    }
422}
423
424#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
425#[serde(rename_all = "camelCase")]
426pub struct V1MetaDisplayScale {
427    pub lower: f64,
428    pub upper: f64,
429    #[serde(rename = "type")]
430    pub type_: Option<String>,
431    pub power: Option<f64>,
432}
433
434impl V1MetaDisplayScale {
435    pub fn builder() -> V1MetaDisplayScaleBuilder {
436        V1MetaDisplayScaleBuilder::default()
437    }
438}
439
440#[derive(Default)]
441pub struct V1MetaDisplayScaleBuilder {
442    lower: f64,
443    upper: f64,
444    type_: Option<String>,
445    power: Option<f64>,
446}
447
448impl V1MetaDisplayScaleBuilder {
449    pub fn lower(mut self, value: f64) -> V1MetaDisplayScaleBuilder {
450        self.lower = value;
451        self
452    }
453    pub fn upper(mut self, value: f64) -> V1MetaDisplayScaleBuilder {
454        self.upper = value;
455        self
456    }
457    pub fn type_(mut self, value: String) -> V1MetaDisplayScaleBuilder {
458        self.type_ = Some(value);
459        self
460    }
461    pub fn power(mut self, value: f64) -> V1MetaDisplayScaleBuilder {
462        self.power = Some(value);
463        self
464    }
465
466    pub fn build(self) -> V1MetaDisplayScale {
467        V1MetaDisplayScale {
468            lower: self.lower,
469            upper: self.upper,
470            type_: self.type_,
471            power: self.power,
472        }
473    }
474}
475
476#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
477#[serde(rename_all = "camelCase")]
478pub struct V1MetaZone {
479    pub lower: Option<f64>,
480    pub upper: Option<f64>,
481    pub state: String,
482    pub message: Option<String>,
483}
484
485impl V1MetaZone {
486    pub fn builder() -> V1MetaZoneBuilder {
487        V1MetaZoneBuilder::default()
488    }
489}
490
491#[derive(Default)]
492pub struct V1MetaZoneBuilder {
493    lower: Option<f64>,
494    upper: Option<f64>,
495    state: String,
496    message: Option<String>,
497}
498
499impl V1MetaZoneBuilder {
500    pub fn lower(mut self, value: f64) -> V1MetaZoneBuilder {
501        self.lower = Some(value);
502        self
503    }
504    pub fn upper(mut self, value: f64) -> V1MetaZoneBuilder {
505        self.upper = Some(value);
506        self
507    }
508    pub fn state(mut self, value: String) -> V1MetaZoneBuilder {
509        self.state = value;
510        self
511    }
512    pub fn message(mut self, value: String) -> V1MetaZoneBuilder {
513        self.message = Some(value);
514        self
515    }
516
517    pub fn build(self) -> V1MetaZone {
518        V1MetaZone {
519            lower: self.lower,
520            upper: self.upper,
521            state: self.state,
522            message: self.message,
523        }
524    }
525}
526
527#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
528pub struct V1Attr {
529    #[serde(rename = "_mode")]
530    pub mode: Option<i64>,
531    #[serde(rename = "_owner")]
532    pub owner: Option<String>,
533    #[serde(rename = "_group")]
534    pub group: Option<String>,
535}
536
537impl Default for V1Attr {
538    fn default() -> Self {
539        V1Attr {
540            mode: Some(644),
541            owner: Some("self".into()),
542            group: Some("self".into()),
543        }
544    }
545}
546
547impl V1Attr {
548    pub fn new(mode: i64, owner: String, group: String) -> V1Attr {
549        V1Attr {
550            mode: Some(mode),
551            owner: Some(owner),
552            group: Some(group),
553        }
554    }
555}
556
557#[derive(Serialize, Deserialize, PartialEq, Debug, Default)]
558#[serde(rename_all = "camelCase")]
559pub struct V1DefSource {
560    pub label: String,
561    #[serde(rename = "type")]
562    pub type_: Option<String>,
563    pub src: Option<String>,
564    pub can_name: Option<String>,
565    pub pgn: Option<i32>,
566    pub instance: Option<String>,
567    pub sentence: Option<String>,
568    pub talker: Option<String>,
569    pub ais_type: Option<i32>,
570}
571
572impl V1DefSource {
573    pub fn builder() -> V1DefSourceBuilder {
574        V1DefSourceBuilder::default()
575    }
576}
577
578#[derive(Default)]
579pub struct V1DefSourceBuilder {
580    label: String,
581    type_: Option<String>,
582    src: Option<String>,
583    can_name: Option<String>,
584    pgn: Option<i32>,
585    instance: Option<String>,
586    sentence: Option<String>,
587    talker: Option<String>,
588    ais_type: Option<i32>,
589}
590
591impl V1DefSourceBuilder {
592    pub fn label(mut self, value: String) -> V1DefSourceBuilder {
593        self.label = value;
594        self
595    }
596    pub fn type_(mut self, value: String) -> V1DefSourceBuilder {
597        self.type_ = Some(value);
598        self
599    }
600    pub fn src(mut self, value: String) -> V1DefSourceBuilder {
601        self.src = Some(value);
602        self
603    }
604    pub fn can_name(mut self, value: String) -> V1DefSourceBuilder {
605        self.can_name = Some(value);
606        self
607    }
608    pub fn pgn(mut self, value: i32) -> V1DefSourceBuilder {
609        self.pgn = Some(value);
610        self
611    }
612    pub fn instance(mut self, value: String) -> V1DefSourceBuilder {
613        self.instance = Some(value);
614        self
615    }
616    pub fn sentence(mut self, value: String) -> V1DefSourceBuilder {
617        self.sentence = Some(value);
618        self
619    }
620    pub fn talker(mut self, value: String) -> V1DefSourceBuilder {
621        self.talker = Some(value);
622        self
623    }
624    pub fn ais_type(mut self, value: i32) -> V1DefSourceBuilder {
625        self.ais_type = Some(value);
626        self
627    }
628    pub fn build(self) -> V1DefSource {
629        V1DefSource {
630            label: self.label,
631            type_: self.type_,
632            src: self.src,
633            can_name: self.can_name,
634            pgn: self.pgn,
635            instance: self.instance,
636            sentence: self.sentence,
637            talker: self.talker,
638            ais_type: self.ais_type,
639        }
640    }
641}
642
643#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
644#[serde(untagged)]
645pub enum V1DateTime {
646    #[default]
647    None,
648    String(String),
649    Object(V1DateTimeValue),
650}
651
652impl V1DateTime {
653    pub fn builder() -> V1DateTimeBuilder {
654        V1DateTimeBuilder::default()
655    }
656
657    pub fn from_value(value: &Value) -> Option<V1DateTime> {
658        if value.is_null() {
659            None
660        } else {
661            let type_result: Result<V1DateTime, serde_json::Error> =
662                serde_json::from_value(value.clone());
663            if let Ok(type_value) = type_result {
664                Some(type_value)
665            } else {
666                None
667            }
668        }
669    }
670
671    #[allow(clippy::manual_unwrap_or_default)]
672    fn get_value(&self) -> &str {
673        match self {
674            V1DateTime::None => "",
675            V1DateTime::String(val) => val,
676            V1DateTime::Object(ref o) => match o.value {
677                None => "",
678                Some(ref value) => value,
679            },
680        }
681    }
682    pub fn get_hour(&self) -> u8 {
683        let value = self.get_value();
684        let time = OffsetDateTime::parse(value, &Rfc3339);
685        if let Ok(time) = time {
686            time.hour()
687        } else {
688            0
689        }
690    }
691    pub fn get_minute(&self) -> u8 {
692        let value = self.get_value();
693        let time = OffsetDateTime::parse(value, &Rfc3339);
694        if let Ok(time) = time {
695            time.minute()
696        } else {
697            0
698        }
699    }
700    pub fn get_second(&self) -> u8 {
701        let value = self.get_value();
702        let time = OffsetDateTime::parse(value, &Rfc3339);
703        if let Ok(time) = time {
704            time.second()
705        } else {
706            0
707        }
708    }
709}
710
711#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
712pub struct V1DateTimeValue {
713    value: Option<String>,
714    timestamp: Option<String>,
715    pgn: Option<i64>,
716    sentence: Option<String>,
717}
718
719#[derive(Default)]
720pub struct V1DateTimeBuilder {
721    value: Option<String>,
722    _object: Option<V1DateTimeValue>,
723}
724
725impl V1DateTimeBuilder {
726    pub fn timestamp(mut self, value: String) -> V1DateTimeBuilder {
727        self.value = Some(value);
728        self
729    }
730
731    pub fn build(self) -> V1DateTime {
732        V1DateTime::None
733    }
734}
735
736#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
737pub struct V1Timestamp {
738    #[serde(flatten)]
739    pub value: Option<String>,
740}
741
742impl V1Timestamp {
743    pub fn builder() -> V1TimestampBuilder {
744        V1TimestampBuilder::default()
745    }
746}
747
748#[derive(Default)]
749pub struct V1TimestampBuilder {
750    pub value: Option<String>,
751}
752
753impl V1TimestampBuilder {
754    pub fn value(mut self, value: String) -> V1TimestampBuilder {
755        self.value = Some(value);
756        self
757    }
758    pub fn build(self) -> V1Timestamp {
759        V1Timestamp { value: self.value }
760    }
761}
762
763#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
764#[serde(untagged)]
765pub enum V1StringValue {
766    Expanded(V1StringExpandedValue),
767    Value(String),
768}
769
770impl Default for V1StringValue {
771    fn default() -> Self {
772        V1StringValue::Value(String::default())
773    }
774}
775
776impl V1StringValue {
777    pub fn builder() -> V1StringValueBuilder {
778        V1StringValueBuilder::default()
779    }
780
781    pub fn from_value(value: &Value) -> Option<V1StringValue> {
782        if value.is_null() {
783            None
784        } else {
785            let type_result: Result<V1StringValue, serde_json::Error> =
786                serde_json::from_value(value.clone());
787            if let Ok(type_value) = type_result {
788                Some(type_value)
789            } else {
790                None
791            }
792        }
793    }
794}
795
796#[derive(Default)]
797pub struct V1StringValueBuilder {
798    value: Option<String>,
799    common_value_fields: Option<V1CommonValueFields>,
800}
801impl V1StringValueBuilder {
802    pub fn value(mut self, value: String) -> V1StringValueBuilder {
803        self.value = Some(value);
804        self
805    }
806    pub fn common_value_fields(mut self, value: V1CommonValueFields) -> V1StringValueBuilder {
807        self.common_value_fields = Some(value);
808        self
809    }
810
811    pub fn build(self) -> V1StringValue {
812        if let Some(ref _value) = self.common_value_fields {
813            V1StringValue::Expanded(V1StringExpandedValue {
814                value: self.value,
815                common_value_fields: self.common_value_fields,
816            })
817        } else if let Some(value) = self.value {
818            V1StringValue::Value(value.clone())
819        } else {
820            V1StringValue::Value("".to_string())
821        }
822    }
823}
824
825#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Clone)]
826pub struct V1StringExpandedValue {
827    pub value: Option<String>,
828    #[serde(flatten)]
829    pub common_value_fields: Option<V1CommonValueFields>,
830}
831
832#[cfg(test)]
833mod tests {
834    use crate::definitions::{V1DateTime, V1DateTimeValue};
835
836    #[test]
837    fn datetime_object_json() {
838        let j = r#"
839        {
840          "value": "2015-12-05T13:11:59Z",
841          "gnssTimeSource": "GPS",
842          "timestamp": "2014-08-15T19:00:15.123456789Z",
843          "$source": "foo.bar"
844        }"#;
845        let datetime: V1DateTime = serde_json::from_str(j).unwrap();
846        assert_eq!(datetime.get_value(), "2015-12-05T13:11:59Z")
847    }
848
849    #[test]
850    fn datetime_value_object_json() {
851        let j = r#"
852        {
853          "value": "2015-12-05T13:11:59Z",
854          "gnssTimeSource": "GPS",
855          "timestamp": "2014-08-15T19:00:15.123456789Z",
856          "$source": "foo.bar"
857        }"#;
858        let datetime: V1DateTimeValue = serde_json::from_str(j).unwrap();
859        assert_eq!(datetime.value.unwrap(), "2015-12-05T13:11:59Z")
860    }
861    #[test]
862    fn datetime_value_null_value_object_() {
863        let j = r#"
864        {
865          "value": null,
866          "gnssTimeSource": "GPS",
867          "timestamp": "2014-08-15T19:00:15.123456789Z",
868          "$source": "foo.bar"
869        }"#;
870        let datetime: V1DateTimeValue = serde_json::from_str(j).unwrap();
871        assert_eq!(datetime.value, None)
872    }
873
874    #[test]
875    fn datetime_string_json() {
876        let j = r#""2014-08-15T19:05:29.57200Z""#;
877        let datetime: V1DateTime = serde_json::from_str(j).unwrap();
878        assert_eq!(datetime.get_value(), "2014-08-15T19:05:29.57200Z")
879    }
880    #[test]
881    fn datetime_string_2022_json() {
882        let j = r#""2022-04-22T05:02:56.484Z""#;
883        let datetime: V1DateTime = serde_json::from_str(j).unwrap();
884        assert_eq!(datetime.get_value(), "2022-04-22T05:02:56.484Z")
885    }
886
887    #[test]
888    fn date_time_creation() {
889        let date_time = V1DateTime::String("2015-12-05T13:11:59Z".into());
890        println!("{:?}", date_time);
891        assert!(matches!(date_time, V1DateTime::String(_)));
892    }
893}