1use anyhow::Result;
2use chrono::NaiveDateTime;
3use noisy_float::prelude::*;
4use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
5use std::path::PathBuf;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
8#[serde(rename = "dataset")]
9pub struct Dataset {
10 #[serde(rename = "$value")]
11 pub frames: Vec<Frame>,
12}
13
14#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
15#[serde(rename = "frame")]
16pub struct Frame {
17 pub number: usize,
18 pub file: PathBuf,
19 #[serde(with = "serde_utc")]
20 pub utc: NaiveDateTime,
21 pub color: Option<Color>,
22 pub depth: Option<Depth>,
23 pub gsd: R64,
24 pub x: R64,
25 pub y: R64,
26 pub lat: R64,
27 pub lon: R64,
28 #[serde(with = "serde_zero_one_bool")]
29 pub sunny: bool,
30 #[serde(rename = "$value")]
31 pub object_list: ObjectList,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
35#[serde(rename = "objectlist")]
36pub struct ObjectList {
37 #[serde(rename = "$value")]
38 pub objects: Vec<Object>,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
42#[serde(rename = "object")]
43pub struct Object {
44 pub id: usize,
45 pub r#box: Box,
46 pub representation: Representation,
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
50#[serde(rename = "box")]
51pub struct Box {
52 pub xc: R64,
53 pub yc: R64,
54 pub w: R64,
55 pub h: R64,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
59#[serde(rename = "representation")]
60pub struct Representation {
61 pub r#type: RepresentationType,
62 pub xc: R64,
63 pub yc: R64,
64 pub w: R64,
65 pub h: R64,
66 pub o: R64,
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
70pub enum RepresentationType {
71 RotatedRectangle,
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
75pub enum Color {
76 #[serde(rename = "rgb")]
77 Rgb,
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
81pub enum Depth {
82 #[serde(rename = "byte")]
83 Byte,
84}
85
86mod serde_utc {
87 use super::*;
88
89 const FORMAT: &str = "%Y-%b-%d %H:%M:%S%.f";
90
91 pub fn serialize<S>(value: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
92 where
93 S: Serializer,
94 {
95 format!("{}", value.format(FORMAT)).serialize(serializer)
96 }
97
98 pub fn deserialize<'de, D>(deserializer: D) -> Result<NaiveDateTime, D::Error>
99 where
100 D: Deserializer<'de>,
101 {
102 let text = String::deserialize(deserializer)?;
103 NaiveDateTime::parse_from_str(&text, FORMAT).map_err(|err| {
104 D::Error::custom(format!(
105 "unable to deserialize string '{}' to date: {:?}",
106 text, err
107 ))
108 })
109 }
110}
111
112mod serde_zero_one_bool {
113 use super::*;
114
115 pub fn serialize<S>(value: &bool, serializer: S) -> Result<S::Ok, S::Error>
116 where
117 S: Serializer,
118 {
119 if *value { "1" } else { "0" }.serialize(serializer)
120 }
121
122 pub fn deserialize<'de, D>(deserializer: D) -> Result<bool, D::Error>
123 where
124 D: Deserializer<'de>,
125 {
126 let text = String::deserialize(deserializer)?;
127 let value = match &*text {
128 "0" => false,
129 "1" => true,
130 text => {
131 return Err(D::Error::custom(format!(
132 r#"expect "0" or "1", but get "{}""#,
133 text
134 )))
135 }
136 };
137 Ok(value)
138 }
139}
140
141