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