1#![no_std]
2
3extern crate alloc;
4
5use core::fmt::Display;
6use core::marker::PhantomData;
7
8use serde::de::IntoDeserializer;
9
10#[derive(serde::Deserialize, serde::Serialize)]
11pub struct Measurement<Attrs, Sym> {
12 pub name: Sym,
13 pub attributes: Attrs,
14 pub ts: i64,
15 #[serde(bound = "Sym: Display")]
16 pub value: Value<Sym>,
17}
18
19impl From<whalesong::Measurement> for Measurement<whalesong::Attributes, whalesong::Symbol> {
20 fn from(meas: whalesong::Measurement) -> Self {
21 Self {
22 name: meas.name,
23 attributes: meas.attributes,
24 ts: meas.ts.timestamp_millis(),
25 value: meas.value.into(),
26 }
27 }
28}
29
30#[derive(Clone)]
31pub enum Value<Sym> {
32 Number(f64),
33 Boolean(bool),
34 Symbol(Sym),
35}
36
37impl<Sym> Value<Sym>
38where
39 Sym: whalesong::SymbolLookup,
40{
41 pub fn manifest(self, legend: &mut whalesong::Legend) -> whalesong::Value {
42 match self {
43 Self::Number(v) => whalesong::Value::Number(v),
44 Self::Boolean(v) => whalesong::Value::Boolean(v),
45 Self::Symbol(v) => whalesong::Value::Symbol(legend.register(&v).clone()),
46 }
47 }
48}
49
50impl From<whalesong::Value> for Value<whalesong::Symbol> {
51 fn from(value: whalesong::Value) -> Self {
52 match value {
53 whalesong::Value::Number(v) => Self::Number(v),
54 whalesong::Value::Boolean(v) => Self::Boolean(v),
55 whalesong::Value::Symbol(v) => Self::Symbol(v),
56 }
57 }
58}
59
60impl<Sym> serde::Serialize for Value<Sym>
61where
62 Sym: Display,
63{
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: serde::Serializer,
67 {
68 match self {
69 Self::Number(v) => serializer.serialize_f64(*v),
70 Self::Boolean(v) => serializer.serialize_bool(*v),
71 Self::Symbol(v) => serializer.collect_str(v),
72 }
73 }
74}
75
76impl<'de, Sym> serde::Deserialize<'de> for Value<Sym>
77where
78 Sym: serde::Deserialize<'de>,
79{
80 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81 where
82 D: serde::Deserializer<'de>,
83 {
84 struct Visitor<Sym> {
85 _p: PhantomData<Sym>,
86 }
87
88 impl<'de, Sym> serde::de::Visitor<'de> for Visitor<Sym>
89 where
90 Sym: serde::Deserialize<'de>,
91 {
92 type Value = Value<Sym>;
93
94 fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
95 formatter.write_str("whalesong::Value")
96 }
97
98 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
101 where
102 E: serde::de::Error,
103 {
104 Ok(Value::Boolean(v))
105 }
106
107 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
110 where
111 E: serde::de::Error,
112 {
113 Ok(Value::Number(v))
114 }
115
116 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
117 where
118 E: serde::de::Error,
119 {
120 self.visit_f64(f64::from(v))
121 }
122
123 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
124 where
125 E: serde::de::Error,
126 {
127 let v_f64 = v as f64;
128 if v_f64 as u64 == v {
129 Ok(Value::Number(v_f64))
130 } else {
131 Err(E::custom("number not representable"))
132 }
133 }
134
135 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
136 where
137 E: serde::de::Error,
138 {
139 self.visit_f64(f64::from(v))
140 }
141
142 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
143 where
144 E: serde::de::Error,
145 {
146 let v_f64 = v as f64;
147 if v_f64 as i64 == v {
148 Ok(Value::Number(v_f64))
149 } else {
150 Err(E::custom("number not representable"))
151 }
152 }
153
154 fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
157 where
158 E: serde::de::Error,
159 {
160 Sym::deserialize(v.into_deserializer()).map(Value::Symbol)
161 }
162
163 fn visit_byte_buf<E>(self, v: alloc::vec::Vec<u8>) -> Result<Self::Value, E>
164 where
165 E: serde::de::Error,
166 {
167 Sym::deserialize(v.into_deserializer()).map(Value::Symbol)
168 }
169
170 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
171 where
172 E: serde::de::Error,
173 {
174 Sym::deserialize(v.into_deserializer()).map(Value::Symbol)
175 }
176
177 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
178 where
179 E: serde::de::Error,
180 {
181 Sym::deserialize(v.into_deserializer()).map(Value::Symbol)
182 }
183
184 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
185 where
186 E: serde::de::Error,
187 {
188 Sym::deserialize(v.into_deserializer()).map(Value::Symbol)
189 }
190
191 fn visit_string<E>(self, v: alloc::string::String) -> Result<Self::Value, E>
192 where
193 E: serde::de::Error,
194 {
195 Sym::deserialize(v.into_deserializer()).map(Value::Symbol)
196 }
197 }
198
199 deserializer.deserialize_any(Visitor { _p: PhantomData })
200 }
201}