1use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5use std::fmt;
6use std::sync::Arc;
7
8use super::Timestamp;
9
10#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
15pub struct PropertyKey(Arc<str>);
16
17impl PropertyKey {
18 #[must_use]
20 pub fn new(s: impl Into<Arc<str>>) -> Self {
21 Self(s.into())
22 }
23
24 #[must_use]
26 pub fn as_str(&self) -> &str {
27 &self.0
28 }
29}
30
31impl fmt::Debug for PropertyKey {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "PropertyKey({:?})", self.0)
34 }
35}
36
37impl fmt::Display for PropertyKey {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(f, "{}", self.0)
40 }
41}
42
43impl From<&str> for PropertyKey {
44 fn from(s: &str) -> Self {
45 Self::new(s)
46 }
47}
48
49impl From<String> for PropertyKey {
50 fn from(s: String) -> Self {
51 Self::new(s)
52 }
53}
54
55impl AsRef<str> for PropertyKey {
56 fn as_ref(&self) -> &str {
57 &self.0
58 }
59}
60
61#[derive(Clone, PartialEq, Serialize, Deserialize)]
66pub enum Value {
67 Null,
69
70 Bool(bool),
72
73 Int64(i64),
75
76 Float64(f64),
78
79 String(Arc<str>),
81
82 Bytes(Arc<[u8]>),
84
85 Timestamp(Timestamp),
87
88 List(Arc<[Value]>),
90
91 Map(Arc<BTreeMap<PropertyKey, Value>>),
93}
94
95impl Value {
96 #[inline]
98 #[must_use]
99 pub const fn is_null(&self) -> bool {
100 matches!(self, Value::Null)
101 }
102
103 #[inline]
105 #[must_use]
106 pub const fn as_bool(&self) -> Option<bool> {
107 match self {
108 Value::Bool(b) => Some(*b),
109 _ => None,
110 }
111 }
112
113 #[inline]
115 #[must_use]
116 pub const fn as_int64(&self) -> Option<i64> {
117 match self {
118 Value::Int64(i) => Some(*i),
119 _ => None,
120 }
121 }
122
123 #[inline]
125 #[must_use]
126 pub const fn as_float64(&self) -> Option<f64> {
127 match self {
128 Value::Float64(f) => Some(*f),
129 _ => None,
130 }
131 }
132
133 #[inline]
135 #[must_use]
136 pub fn as_str(&self) -> Option<&str> {
137 match self {
138 Value::String(s) => Some(s),
139 _ => None,
140 }
141 }
142
143 #[inline]
145 #[must_use]
146 pub fn as_bytes(&self) -> Option<&[u8]> {
147 match self {
148 Value::Bytes(b) => Some(b),
149 _ => None,
150 }
151 }
152
153 #[inline]
155 #[must_use]
156 pub const fn as_timestamp(&self) -> Option<Timestamp> {
157 match self {
158 Value::Timestamp(t) => Some(*t),
159 _ => None,
160 }
161 }
162
163 #[inline]
165 #[must_use]
166 pub fn as_list(&self) -> Option<&[Value]> {
167 match self {
168 Value::List(l) => Some(l),
169 _ => None,
170 }
171 }
172
173 #[inline]
175 #[must_use]
176 pub fn as_map(&self) -> Option<&BTreeMap<PropertyKey, Value>> {
177 match self {
178 Value::Map(m) => Some(m),
179 _ => None,
180 }
181 }
182
183 #[must_use]
185 pub const fn type_name(&self) -> &'static str {
186 match self {
187 Value::Null => "NULL",
188 Value::Bool(_) => "BOOL",
189 Value::Int64(_) => "INT64",
190 Value::Float64(_) => "FLOAT64",
191 Value::String(_) => "STRING",
192 Value::Bytes(_) => "BYTES",
193 Value::Timestamp(_) => "TIMESTAMP",
194 Value::List(_) => "LIST",
195 Value::Map(_) => "MAP",
196 }
197 }
198
199 #[must_use]
201 pub fn serialize(&self) -> Vec<u8> {
202 bincode::serde::encode_to_vec(self, bincode::config::standard())
203 .expect("Value serialization should not fail")
204 }
205
206 pub fn deserialize(bytes: &[u8]) -> Result<Self, bincode::error::DecodeError> {
212 let (value, _) = bincode::serde::decode_from_slice(bytes, bincode::config::standard())?;
213 Ok(value)
214 }
215}
216
217impl fmt::Debug for Value {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 match self {
220 Value::Null => write!(f, "Null"),
221 Value::Bool(b) => write!(f, "Bool({b})"),
222 Value::Int64(i) => write!(f, "Int64({i})"),
223 Value::Float64(fl) => write!(f, "Float64({fl})"),
224 Value::String(s) => write!(f, "String({s:?})"),
225 Value::Bytes(b) => write!(f, "Bytes([{}; {} bytes])", b.first().unwrap_or(&0), b.len()),
226 Value::Timestamp(t) => write!(f, "Timestamp({t:?})"),
227 Value::List(l) => write!(f, "List({l:?})"),
228 Value::Map(m) => write!(f, "Map({m:?})"),
229 }
230 }
231}
232
233impl fmt::Display for Value {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 match self {
236 Value::Null => write!(f, "NULL"),
237 Value::Bool(b) => write!(f, "{b}"),
238 Value::Int64(i) => write!(f, "{i}"),
239 Value::Float64(fl) => write!(f, "{fl}"),
240 Value::String(s) => write!(f, "{s:?}"),
241 Value::Bytes(b) => write!(f, "<bytes: {} bytes>", b.len()),
242 Value::Timestamp(t) => write!(f, "{t}"),
243 Value::List(l) => {
244 write!(f, "[")?;
245 for (i, v) in l.iter().enumerate() {
246 if i > 0 {
247 write!(f, ", ")?;
248 }
249 write!(f, "{v}")?;
250 }
251 write!(f, "]")
252 }
253 Value::Map(m) => {
254 write!(f, "{{")?;
255 for (i, (k, v)) in m.iter().enumerate() {
256 if i > 0 {
257 write!(f, ", ")?;
258 }
259 write!(f, "{k}: {v}")?;
260 }
261 write!(f, "}}")
262 }
263 }
264 }
265}
266
267impl From<bool> for Value {
269 fn from(b: bool) -> Self {
270 Value::Bool(b)
271 }
272}
273
274impl From<i64> for Value {
275 fn from(i: i64) -> Self {
276 Value::Int64(i)
277 }
278}
279
280impl From<i32> for Value {
281 fn from(i: i32) -> Self {
282 Value::Int64(i64::from(i))
283 }
284}
285
286impl From<f64> for Value {
287 fn from(f: f64) -> Self {
288 Value::Float64(f)
289 }
290}
291
292impl From<f32> for Value {
293 fn from(f: f32) -> Self {
294 Value::Float64(f64::from(f))
295 }
296}
297
298impl From<&str> for Value {
299 fn from(s: &str) -> Self {
300 Value::String(s.into())
301 }
302}
303
304impl From<String> for Value {
305 fn from(s: String) -> Self {
306 Value::String(s.into())
307 }
308}
309
310impl From<Arc<str>> for Value {
311 fn from(s: Arc<str>) -> Self {
312 Value::String(s)
313 }
314}
315
316impl From<Vec<u8>> for Value {
317 fn from(b: Vec<u8>) -> Self {
318 Value::Bytes(b.into())
319 }
320}
321
322impl From<&[u8]> for Value {
323 fn from(b: &[u8]) -> Self {
324 Value::Bytes(b.into())
325 }
326}
327
328impl From<Timestamp> for Value {
329 fn from(t: Timestamp) -> Self {
330 Value::Timestamp(t)
331 }
332}
333
334impl<T: Into<Value>> From<Vec<T>> for Value {
335 fn from(v: Vec<T>) -> Self {
336 Value::List(v.into_iter().map(Into::into).collect())
337 }
338}
339
340impl<T: Into<Value>> From<Option<T>> for Value {
341 fn from(opt: Option<T>) -> Self {
342 match opt {
343 Some(v) => v.into(),
344 None => Value::Null,
345 }
346 }
347}
348
349#[cfg(test)]
350mod tests {
351 use super::*;
352
353 #[test]
354 fn test_value_type_checks() {
355 assert!(Value::Null.is_null());
356 assert!(!Value::Bool(true).is_null());
357
358 assert_eq!(Value::Bool(true).as_bool(), Some(true));
359 assert_eq!(Value::Bool(false).as_bool(), Some(false));
360 assert_eq!(Value::Int64(42).as_bool(), None);
361
362 assert_eq!(Value::Int64(42).as_int64(), Some(42));
363 assert_eq!(Value::String("test".into()).as_int64(), None);
364
365 assert_eq!(Value::Float64(1.234).as_float64(), Some(1.234));
366 assert_eq!(Value::String("hello".into()).as_str(), Some("hello"));
367 }
368
369 #[test]
370 fn test_value_from_conversions() {
371 let v: Value = true.into();
372 assert_eq!(v.as_bool(), Some(true));
373
374 let v: Value = 42i64.into();
375 assert_eq!(v.as_int64(), Some(42));
376
377 let v: Value = 1.234f64.into();
378 assert_eq!(v.as_float64(), Some(1.234));
379
380 let v: Value = "hello".into();
381 assert_eq!(v.as_str(), Some("hello"));
382
383 let v: Value = vec![1u8, 2, 3].into();
384 assert_eq!(v.as_bytes(), Some(&[1u8, 2, 3][..]));
385 }
386
387 #[test]
388 fn test_value_serialization_roundtrip() {
389 let values = vec![
390 Value::Null,
391 Value::Bool(true),
392 Value::Int64(i64::MAX),
393 Value::Float64(std::f64::consts::PI),
394 Value::String("hello world".into()),
395 Value::Bytes(vec![0, 1, 2, 255].into()),
396 Value::List(vec![Value::Int64(1), Value::Int64(2)].into()),
397 ];
398
399 for v in values {
400 let bytes = v.serialize();
401 let decoded = Value::deserialize(&bytes).unwrap();
402 assert_eq!(v, decoded);
403 }
404 }
405
406 #[test]
407 fn test_property_key() {
408 let key = PropertyKey::new("name");
409 assert_eq!(key.as_str(), "name");
410
411 let key2: PropertyKey = "age".into();
412 assert_eq!(key2.as_str(), "age");
413
414 assert!(key2 < key);
416 }
417
418 #[test]
419 fn test_value_type_name() {
420 assert_eq!(Value::Null.type_name(), "NULL");
421 assert_eq!(Value::Bool(true).type_name(), "BOOL");
422 assert_eq!(Value::Int64(0).type_name(), "INT64");
423 assert_eq!(Value::Float64(0.0).type_name(), "FLOAT64");
424 assert_eq!(Value::String("".into()).type_name(), "STRING");
425 assert_eq!(Value::Bytes(vec![].into()).type_name(), "BYTES");
426 assert_eq!(Value::List(vec![].into()).type_name(), "LIST");
427 assert_eq!(Value::Map(BTreeMap::new().into()).type_name(), "MAP");
428 }
429}