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 }
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}