netidx_value/
lib.rs

1//! Universal value type for netidx pub/sub.
2//!
3//! This crate provides [`Value`], a dynamically-typed enum that can represent
4//! any data type publishable in netidx. Values support 25+ built-in types
5//! including integers, floats, strings, bytes, arrays, maps, decimals,
6//! timestamps, and durations.
7//!
8//! ## Key Features
9//!
10//! - **Rich type system**: Integers (with LEB128 varint encoding), floats,
11//!   strings, bytes, arrays, maps, decimals, timestamps, durations
12//! - **Efficient cloning**: Small values (≤64 bits) are bitwise copied;
13//!   larger values use reference counting
14//! - **User-defined types**: Register custom types with the [`Abstract`] wrapper
15//! - **Wire-efficient**: Compact binary encoding via [`Pack`]
16//! - **Parsing & printing**: Parse from strings, format for display
17//!
18//! ## Example
19//!
20//! ```no_run
21//! # fn main() -> anyhow::Result<()> {
22//! use netidx_value::Value;
23//!
24//! let v = Value::I64(42);
25//! assert_eq!(v.clone().cast_to::<f64>()?, 42.0);
26//!
27//! let s = Value::String("hello".into());
28//! let arr = Value::Array(vec![v, s].into());
29//! # Ok(()) }
30//! ```
31//!
32//! ## User-Defined Types
33//!
34//! You can register your own types using the abstract type system. Each type
35//! needs a unique UUID and must implement `Pack`, `Debug`, `Hash`, `Eq`, and `Ord`:
36//!
37//! ```
38//! use netidx_value::{Value, Abstract};
39//! use netidx_core::pack::Pack;
40//! use netidx_derive::Pack;
41//! use uuid::uuid;
42//! # fn main() -> anyhow::Result<()> {
43//! #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Pack)]
44//! struct Custom {
45//!     field1: u32,
46//!     field2: String,
47//! }
48//!
49//! // Register with a unique UUID (generate once, hardcode in your program)
50//! const CUSTOM_TYPE_ID: uuid::Uuid = uuid!("550e8400-e29b-41d4-a716-446655440000");
51//!
52//! let wrapper = Abstract::register::<Custom>(CUSTOM_TYPE_ID)?;
53//! let t = Custom { field1: 42, field2: "test".into() };
54//! let abstract_value: Value = wrapper.wrap(t).into();
55//!
56//! // Later, downcast back to your type
57//! if let Some(t) = abstract_value.downcast_ref::<Custom>() {
58//!     println!("field1: {}", t.field1);
59//! }
60//! # Ok(()) }
61//! ```
62//!
63//! ## Type Casting
64//!
65//! Values support casting between compatible types using [`Value::cast_to()`].
66//! For example, integers can be cast to floats, and vice versa (with range checking).
67
68use anyhow::Result;
69use arcstr::ArcStr;
70use bytes::{Buf, BufMut};
71use chrono::prelude::*;
72use compact_str::{format_compact, CompactString};
73use immutable_chunkmap::map;
74use netidx_core::{
75    pack::{self, Pack, PackError},
76    utils,
77};
78use rust_decimal::Decimal;
79use serde::{Deserialize, Serialize};
80use smallvec::SmallVec;
81use std::{
82    any::Any, hint::unreachable_unchecked, iter, ptr, result, str::FromStr,
83    time::Duration,
84};
85use triomphe::Arc;
86
87pub mod abstract_type;
88pub mod array;
89mod convert;
90mod op;
91pub mod parser;
92pub mod pbuf;
93mod print;
94#[cfg(test)]
95mod test;
96mod typ;
97
98pub use abstract_type::Abstract;
99pub use array::ValArray;
100pub use convert::FromValue;
101pub use pbuf::PBytes;
102pub use print::{printf, NakedValue};
103pub use typ::Typ;
104
105#[macro_export]
106macro_rules! valarray {
107    ($proto:expr; $size:literal) => {{
108        let proto: Value = $proto.into();
109        Value::Array(std::array::from_fn::<_, $size, _>(|_| proto.clone()))
110    }};
111    ($($e:expr),+) => {
112        Value::Array([$($e.into()),+].into())
113    }
114}
115
116fn _test_valarray() {
117    let v: Value = valarray![1, 2, 5.3, 10];
118    let _: Value = valarray![valarray!["elts", v], valarray!["foo", ["bar"]]];
119}
120
121pub type Map = map::Map<Value, Value, 32>;
122
123const COPY_MAX: u64 = 0x0000_8000;
124
125/// A dynamically-typed value that can be published and subscribed.
126///
127/// This type is divided into two subtypes: copy and clone.
128/// If the tag word is <= COPY_MAX then the type is copy,
129/// otherwise it must be cloned. Additionally, the tag word values are
130/// THE SAME as the values of the cases of Typ. Getting the Typ of a
131/// value is therefore a simply copy of the discriminant of Value.
132///
133/// It is essential that when adding variants you update COPY_MAX and
134/// Typ correctly. If adding a non copy type, you will also need to
135/// update the implementation of clone to match and delegate the clone
136/// operation.
137#[derive(Debug, Serialize, Deserialize)]
138#[serde(tag = "type", content = "value")]
139#[repr(u64)]
140pub enum Value {
141    /// unsigned byte
142    U8(u8) = 0x0000_0001,
143    /// signed byte
144    I8(i8) = 0x0000_0002,
145    /// u16
146    U16(u16) = 0x0000_0004,
147    /// i16
148    I16(i16) = 0x0000_0008,
149    /// full 4 byte u32
150    U32(u32) = 0x0000_0010,
151    /// LEB128 varint, 1 - 5 bytes depending on value
152    V32(u32) = 0x0000_0020,
153    /// full 4 byte i32
154    I32(i32) = 0x0000_0040,
155    /// LEB128 varint zigzag encoded, 1 - 5 bytes depending on abs(value)
156    Z32(i32) = 0x0000_0080,
157    /// full 8 byte u64
158    U64(u64) = 0x0000_0100,
159    /// LEB128 varint, 1 - 10 bytes depending on value
160    V64(u64) = 0x0000_0200,
161    /// full 8 byte i64
162    I64(i64) = 0x0000_0400,
163    /// LEB128 varint zigzag encoded, 1 - 10 bytes depending on abs(value)
164    Z64(i64) = 0x0000_0800,
165    /// 4 byte ieee754 single precision float
166    F32(f32) = 0x0000_1000,
167    /// 8 byte ieee754 double precision float
168    F64(f64) = 0x0000_2000,
169    /// boolean true
170    Bool(bool) = 0x0000_4000,
171    /// Empty value
172    Null = 0x0000_8000,
173    /// unicode string
174    String(ArcStr) = 0x8000_0000,
175    /// byte array
176    Bytes(PBytes) = 0x4000_0000,
177    /// An explicit error
178    Error(Arc<Value>) = 0x2000_0000,
179    /// An array of values
180    Array(ValArray) = 0x1000_0000,
181    /// A Map of values
182    Map(Map) = 0x0800_0000,
183    /// fixed point decimal type
184    Decimal(Arc<Decimal>) = 0x0400_0000,
185    /// UTC timestamp
186    DateTime(Arc<DateTime<Utc>>) = 0x0200_0000,
187    /// Duration
188    Duration(Arc<Duration>) = 0x0100_0000,
189    /// Abstract
190    Abstract(Abstract) = 0x0080_0000,
191}
192
193// This will fail to compile if any variant that is supposed to be
194// Copy changes to not Copy. It is never intended to be called, and it
195// will panic if it ever is.
196fn _assert_variants_are_copy(v: &Value) -> Value {
197    let i = match v {
198        // copy types
199        Value::U8(i) => Value::U8(*i),
200        Value::I8(i) => Value::I8(*i),
201        Value::U16(i) => Value::U16(*i),
202        Value::I16(i) => Value::I16(*i),
203        Value::U32(i) | Value::V32(i) => Value::U32(*i),
204        Value::I32(i) | Value::Z32(i) => Value::I32(*i),
205        Value::U64(i) | Value::V64(i) => Value::U64(*i),
206        Value::I64(i) | Value::Z64(i) => Value::I64(*i),
207        Value::F32(i) => Value::F32(*i),
208        Value::F64(i) => Value::F64(*i),
209        Value::Bool(b) => Value::Bool(*b),
210        Value::Null => Value::Null,
211
212        // not copy types
213        Value::String(i) => Value::String(i.clone()),
214        Value::Bytes(i) => Value::Bytes(i.clone()),
215        Value::Error(i) => Value::Error(i.clone()),
216        Value::Array(i) => Value::Array(i.clone()),
217        Value::Map(i) => Value::Map(i.clone()),
218        Value::Decimal(i) => Value::Decimal(i.clone()),
219        Value::DateTime(i) => Value::DateTime(i.clone()),
220        Value::Duration(i) => Value::Duration(i.clone()),
221        Value::Abstract(i) => Value::Abstract(i.clone()),
222    };
223    panic!("{i}")
224}
225
226impl Clone for Value {
227    fn clone(&self) -> Self {
228        if self.is_copy() {
229            unsafe { ptr::read(self) }
230        } else {
231            match self {
232                Self::String(c) => Self::String(c.clone()),
233                Self::Bytes(b) => Self::Bytes(b.clone()),
234                Self::Error(e) => Self::Error(e.clone()),
235                Self::Array(a) => Self::Array(a.clone()),
236                Self::Map(m) => Self::Map(m.clone()),
237                Self::Decimal(d) => Self::Decimal(d.clone()),
238                Self::DateTime(d) => Self::DateTime(d.clone()),
239                Self::Duration(d) => Self::Duration(d.clone()),
240                Self::Abstract(v) => Self::Abstract(v.clone()),
241                Self::U8(_)
242                | Self::I8(_)
243                | Self::U16(_)
244                | Self::I16(_)
245                | Self::U32(_)
246                | Self::V32(_)
247                | Self::I32(_)
248                | Self::Z32(_)
249                | Self::U64(_)
250                | Self::V64(_)
251                | Self::I64(_)
252                | Self::Z64(_)
253                | Self::F32(_)
254                | Self::F64(_)
255                | Self::Bool(_)
256                | Self::Null => unsafe { unreachable_unchecked() },
257            }
258        }
259    }
260
261    fn clone_from(&mut self, source: &Self) {
262        if source.is_copy() {
263            unsafe { ptr::copy_nonoverlapping(source, self, 1) };
264        } else {
265            match source {
266                Self::String(c) => {
267                    *self = Self::String(c.clone());
268                }
269                Self::Bytes(b) => {
270                    *self = Self::Bytes(b.clone());
271                }
272                Self::Error(e) => {
273                    *self = Self::Error(e.clone());
274                }
275                Self::Array(a) => {
276                    *self = Self::Array(a.clone());
277                }
278                Self::Map(m) => {
279                    *self = Self::Map(m.clone());
280                }
281                Value::Decimal(d) => {
282                    *self = Self::Decimal(d.clone());
283                }
284                Value::DateTime(d) => {
285                    *self = Self::DateTime(d.clone());
286                }
287                Value::Duration(d) => {
288                    *self = Self::Duration(d.clone());
289                }
290                Value::Abstract(v) => {
291                    *self = Self::Abstract(v.clone());
292                }
293                Value::I8(_)
294                | Value::U8(_)
295                | Value::U16(_)
296                | Value::I16(_)
297                | Value::U32(_)
298                | Value::V32(_)
299                | Value::I32(_)
300                | Value::Z32(_)
301                | Value::U64(_)
302                | Value::V64(_)
303                | Value::I64(_)
304                | Value::Z64(_)
305                | Value::F32(_)
306                | Value::F64(_)
307                | Value::Bool(_)
308                | Value::Null => unsafe { unreachable_unchecked() },
309            }
310        }
311    }
312}
313
314impl FromStr for Value {
315    type Err = anyhow::Error;
316
317    fn from_str(s: &str) -> result::Result<Self, Self::Err> {
318        parser::parse_value(s)
319    }
320}
321
322impl Pack for Value {
323    fn encoded_len(&self) -> usize {
324        1 + match self {
325            Value::U8(v) => Pack::encoded_len(v),
326            Value::I8(v) => Pack::encoded_len(v),
327            Value::U16(v) => Pack::encoded_len(v),
328            Value::I16(v) => Pack::encoded_len(v),
329            Value::U32(v) => Pack::encoded_len(v),
330            Value::V32(v) => pack::varint_len(*v as u64),
331            Value::I32(v) => Pack::encoded_len(v),
332            Value::Z32(v) => pack::varint_len(pack::i32_zz(*v) as u64),
333            Value::U64(v) => Pack::encoded_len(v),
334            Value::V64(v) => pack::varint_len(*v),
335            Value::I64(v) => Pack::encoded_len(v),
336            Value::Z64(v) => pack::varint_len(pack::i64_zz(*v) as u64),
337            Value::F32(v) => Pack::encoded_len(v),
338            Value::F64(v) => Pack::encoded_len(v),
339            Value::DateTime(d) => Pack::encoded_len(d),
340            Value::Duration(d) => Pack::encoded_len(d),
341            Value::String(c) => Pack::encoded_len(c),
342            Value::Bytes(b) => Pack::encoded_len(b),
343            Value::Bool(_) | Value::Null => 0,
344            Value::Error(c) => match &**c {
345                Value::String(s) => Pack::encoded_len(s),
346                v => Pack::encoded_len(v),
347            },
348            Value::Array(elts) => Pack::encoded_len(elts),
349            Value::Decimal(d) => Pack::encoded_len(d),
350            Value::Map(m) => Pack::encoded_len(m),
351            Value::Abstract(v) => Pack::encoded_len(v),
352        }
353    }
354
355    // the high two bits of the tag are reserved for wrapper types,
356    // max tag is therefore 0x3F
357    fn encode(&self, buf: &mut impl BufMut) -> result::Result<(), PackError> {
358        match self {
359            Value::U32(i) => {
360                buf.put_u8(0);
361                Pack::encode(i, buf)
362            }
363            Value::V32(i) => {
364                buf.put_u8(1);
365                Ok(pack::encode_varint(*i as u64, buf))
366            }
367            Value::I32(i) => {
368                buf.put_u8(2);
369                Pack::encode(i, buf)
370            }
371            Value::Z32(i) => {
372                buf.put_u8(3);
373                Ok(pack::encode_varint(pack::i32_zz(*i) as u64, buf))
374            }
375            Value::U64(i) => {
376                buf.put_u8(4);
377                Pack::encode(i, buf)
378            }
379            Value::V64(i) => {
380                buf.put_u8(5);
381                Ok(pack::encode_varint(*i, buf))
382            }
383            Value::I64(i) => {
384                buf.put_u8(6);
385                Pack::encode(i, buf)
386            }
387            Value::Z64(i) => {
388                buf.put_u8(7);
389                Ok(pack::encode_varint(pack::i64_zz(*i), buf))
390            }
391            Value::F32(i) => {
392                buf.put_u8(8);
393                Pack::encode(i, buf)
394            }
395            Value::F64(i) => {
396                buf.put_u8(9);
397                Pack::encode(i, buf)
398            }
399            Value::DateTime(dt) => {
400                buf.put_u8(10);
401                Pack::encode(dt, buf)
402            }
403            Value::Duration(d) => {
404                buf.put_u8(11);
405                Pack::encode(d, buf)
406            }
407            Value::String(s) => {
408                buf.put_u8(12);
409                Pack::encode(s, buf)
410            }
411            Value::Bytes(b) => {
412                buf.put_u8(13);
413                Pack::encode(b, buf)
414            }
415            Value::Bool(true) => Ok(buf.put_u8(14)),
416            Value::Bool(false) => Ok(buf.put_u8(15)),
417            Value::Null => Ok(buf.put_u8(16)),
418            //          OK is deprecated, but we reserve 17 for backwards compatibility
419            //          Value::Ok => Ok(buf.put_u8(17))
420            // string error is encoded as 18 for backwards compatibility
421            Value::Array(elts) => {
422                buf.put_u8(19);
423                Pack::encode(elts, buf)
424            }
425            Value::Decimal(d) => {
426                buf.put_u8(20);
427                Pack::encode(d, buf)
428            }
429            Value::Map(m) => {
430                buf.put_u8(21);
431                Pack::encode(m, buf)
432            }
433            Value::Error(e) => match &**e {
434                Value::String(s) => {
435                    buf.put_u8(18);
436                    Pack::encode(s, buf)
437                }
438                v => {
439                    buf.put_u8(22);
440                    Pack::encode(v, buf)
441                }
442            },
443            Value::U8(i) => {
444                buf.put_u8(23);
445                Pack::encode(i, buf)
446            }
447            Value::I8(i) => {
448                buf.put_u8(24);
449                Pack::encode(i, buf)
450            }
451            Value::U16(i) => {
452                buf.put_u8(25);
453                Pack::encode(i, buf)
454            }
455            Value::I16(i) => {
456                buf.put_u8(26);
457                Pack::encode(i, buf)
458            }
459            Value::Abstract(v) => {
460                buf.put_u8(27);
461                Pack::encode(v, buf)
462            }
463        }
464    }
465
466    fn decode(buf: &mut impl Buf) -> result::Result<Self, PackError> {
467        match <u8 as Pack>::decode(buf)? {
468            0 => Ok(Value::U32(Pack::decode(buf)?)),
469            1 => Ok(Value::V32(pack::decode_varint(buf)? as u32)),
470            2 => Ok(Value::I32(Pack::decode(buf)?)),
471            3 => Ok(Value::Z32(pack::i32_uzz(pack::decode_varint(buf)? as u32))),
472            4 => Ok(Value::U64(Pack::decode(buf)?)),
473            5 => Ok(Value::V64(pack::decode_varint(buf)?)),
474            6 => Ok(Value::I64(Pack::decode(buf)?)),
475            7 => Ok(Value::Z64(pack::i64_uzz(pack::decode_varint(buf)?))),
476            8 => Ok(Value::F32(Pack::decode(buf)?)),
477            9 => Ok(Value::F64(Pack::decode(buf)?)),
478            10 => Ok(Value::DateTime(Pack::decode(buf)?)),
479            11 => Ok(Value::Duration(Pack::decode(buf)?)),
480            12 => Ok(Value::String(Pack::decode(buf)?)),
481            13 => Ok(Value::Bytes(Pack::decode(buf)?)),
482            14 => Ok(Value::Bool(true)),
483            15 => Ok(Value::Bool(false)),
484            16 => Ok(Value::Null),
485            17 => Ok(Value::Null), // 17 used to be Ok now translated to Null
486            18 => {
487                // backwards compatible with previous encodings of error when it
488                // was only a string
489                Ok(Value::Error(Arc::new(Value::String(<ArcStr as Pack>::decode(buf)?))))
490            }
491            19 => Ok(Value::Array(Pack::decode(buf)?)),
492            20 => Ok(Value::Decimal(Pack::decode(buf)?)),
493            21 => Ok(Value::Map(Pack::decode(buf)?)),
494            22 => Ok(Value::Error(Arc::new(Pack::decode(buf)?))),
495            23 => Ok(Value::U8(Pack::decode(buf)?)),
496            24 => Ok(Value::I8(Pack::decode(buf)?)),
497            25 => Ok(Value::U16(Pack::decode(buf)?)),
498            26 => Ok(Value::I16(Pack::decode(buf)?)),
499            27 => Ok(Value::Abstract(Pack::decode(buf)?)),
500            _ => Err(PackError::UnknownTag),
501        }
502    }
503}
504
505impl Value {
506    pub fn approx_eq(&self, v: &Self) -> bool {
507        use std::num::FpCategory::*;
508        match (self, v) {
509            (Value::U32(l) | Value::V32(l), Value::U32(r) | Value::V32(r)) => l == r,
510            (Value::I32(l) | Value::Z32(l), Value::I32(r) | Value::Z32(r)) => l == r,
511            (Value::U64(l) | Value::V64(l), Value::U64(r) | Value::V64(r)) => l == r,
512            (Value::I64(l) | Value::Z64(l), Value::I64(r) | Value::Z64(r)) => l == r,
513            (Value::F32(l), Value::F32(r)) => match (l.classify(), r.classify()) {
514                (Nan, Nan) => true,
515                (Zero, Zero) => true,
516                (_, _) => (l - r).abs() <= f32::EPSILON,
517            },
518            (Value::F64(l), Value::F64(r)) => match (l.classify(), r.classify()) {
519                (Nan, Nan) => true,
520                (Zero, Zero) => true,
521                (_, _) => (l - r).abs() <= f64::EPSILON,
522            },
523            (Value::Decimal(l), Value::Decimal(r)) => l == r,
524            (Value::DateTime(l), Value::DateTime(r)) => l == r,
525            (Value::Duration(l), Value::Duration(r)) => {
526                (l.as_secs_f64() - r.as_secs_f64()).abs() <= f64::EPSILON
527            }
528            (Value::String(l), Value::String(r)) => l == r,
529            (Value::Bytes(l), Value::Bytes(r)) => l == r,
530            (Value::Bool(l), Value::Bool(r)) => l == r,
531            (Value::Null, Value::Null) => true,
532            (Value::Error(l), Value::Error(r)) => l.approx_eq(r),
533            (Value::Array(l), Value::Array(r)) => {
534                l.len() == r.len()
535                    && l.iter().zip(r.iter()).all(|(v0, v1)| v0.approx_eq(v1))
536            }
537            (Value::Map(l), Value::Map(r)) => {
538                l.len() == r.len()
539                    && l.into_iter()
540                        .zip(r.into_iter())
541                        .all(|((k0, v0), (k1, v1))| k0.approx_eq(k1) && v0.approx_eq(v1))
542            }
543            (Value::Array(_), _) | (_, Value::Array(_)) => false,
544            (l, r) if l.number() || r.number() => {
545                match (l.clone().cast_to::<f64>(), r.clone().cast_to::<f64>()) {
546                    (Ok(l), Ok(r)) => match (l.classify(), r.classify()) {
547                        (Nan, Nan) => true,
548                        (Zero, Zero) => true,
549                        (_, _) => (l - r).abs() <= f64::EPSILON,
550                    },
551                    (_, _) => false,
552                }
553            }
554            (_, _) => false,
555        }
556    }
557
558    /// return the discriminant tag of this value
559    pub fn discriminant(&self) -> u64 {
560        unsafe { *<*const _>::from(self).cast::<u64>() }
561    }
562
563    /// return true if this value will be cloned by a direct bitwise copy
564    pub fn is_copy(&self) -> bool {
565        self.discriminant() <= COPY_MAX
566    }
567
568    /// Whatever value is attempt to turn it into the type specified
569    pub fn cast(self, typ: Typ) -> Option<Value> {
570        macro_rules! cast_number {
571            ($v:expr, $typ:expr) => {
572                match typ {
573                    Typ::U8 => Some(Value::U8($v as u8)),
574                    Typ::I8 => Some(Value::I8($v as i8)),
575                    Typ::U16 => Some(Value::U16($v as u16)),
576                    Typ::I16 => Some(Value::I16($v as i16)),
577                    Typ::U32 => Some(Value::U32($v as u32)),
578                    Typ::V32 => Some(Value::V32($v as u32)),
579                    Typ::I32 => Some(Value::I32($v as i32)),
580                    Typ::Z32 => Some(Value::Z32($v as i32)),
581                    Typ::U64 => Some(Value::U64($v as u64)),
582                    Typ::V64 => Some(Value::V64($v as u64)),
583                    Typ::I64 => Some(Value::I64($v as i64)),
584                    Typ::Z64 => Some(Value::Z64($v as i64)),
585                    Typ::F32 => Some(Value::F32($v as f32)),
586                    Typ::F64 => Some(Value::F64($v as f64)),
587                    Typ::Decimal => match Decimal::try_from($v) {
588                        Ok(d) => Some(Value::Decimal(Arc::new(d))),
589                        Err(_) => None,
590                    },
591                    Typ::DateTime => Some(Value::DateTime(Arc::new(
592                        DateTime::from_timestamp($v as i64, 0)?,
593                    ))),
594                    Typ::Duration => {
595                        Some(Value::Duration(Arc::new(Duration::from_secs($v as u64))))
596                    }
597                    Typ::Bool => Some(if $v as i64 > 0 {
598                        Value::Bool(true)
599                    } else {
600                        Value::Bool(false)
601                    }),
602                    Typ::String => {
603                        Some(Value::String(format_compact!("{}", self).as_str().into()))
604                    }
605                    Typ::Array => Some(Value::Array([self.clone()].into())),
606                    Typ::Null => Some(Value::Null),
607                    Typ::Bytes | Typ::Error | Typ::Map | Typ::Abstract => None,
608                }
609            };
610        }
611        match self {
612            Value::String(s) => match typ {
613                Typ::String => Some(Value::String(s)),
614                Typ::Error => Some(Value::Error(Arc::new(Value::String(s)))),
615                Typ::Array => Some(Value::Array([Value::String(s)].into())),
616                _ => s.parse::<Value>().ok().and_then(|v| v.cast(typ)),
617            },
618            v if typ == Typ::String => {
619                Some(Value::String(format_compact!("{}", v).as_str().into()))
620            }
621            Value::Map(m) => match typ {
622                Typ::Map => Some(Value::Map(m)),
623                Typ::Array => Some(Value::Array(ValArray::from_iter(m.into_iter().map(
624                    |(k, v)| {
625                        Value::Array(ValArray::from_iter_exact(
626                            [k.clone(), v.clone()].into_iter(),
627                        ))
628                    },
629                )))),
630                _ => None,
631            },
632            Value::Array(elts) => match typ {
633                Typ::Array => Some(Value::Array(elts)),
634                Typ::Map => {
635                    match Value::Array(elts).cast_to::<SmallVec<[(Value, Value); 8]>>() {
636                        Err(_) => None,
637                        Ok(vals) => Some(Value::Map(Map::from_iter(vals))),
638                    }
639                }
640                typ => elts.first().and_then(|v| v.clone().cast(typ)),
641            },
642            Value::U8(v) => cast_number!(v, typ),
643            Value::I8(v) => cast_number!(v, typ),
644            Value::U16(v) => cast_number!(v, typ),
645            Value::I16(v) => cast_number!(v, typ),
646            Value::U32(v) | Value::V32(v) => cast_number!(v, typ),
647            Value::I32(v) | Value::Z32(v) => cast_number!(v, typ),
648            Value::U64(v) | Value::V64(v) => cast_number!(v, typ),
649            Value::I64(v) | Value::Z64(v) => cast_number!(v, typ),
650            Value::F32(v) => cast_number!(v, typ),
651            Value::F64(v) => cast_number!(v, typ),
652            Value::Decimal(v) => match typ {
653                Typ::Decimal => Some(Value::Decimal(v)),
654                Typ::U8 => (*v).try_into().ok().map(Value::U8),
655                Typ::I8 => (*v).try_into().ok().map(Value::I8),
656                Typ::U16 => (*v).try_into().ok().map(Value::U16),
657                Typ::I16 => (*v).try_into().ok().map(Value::I16),
658                Typ::U32 => (*v).try_into().ok().map(Value::U32),
659                Typ::V32 => (*v).try_into().ok().map(Value::V32),
660                Typ::I32 => (*v).try_into().ok().map(Value::I32),
661                Typ::Z32 => (*v).try_into().ok().map(Value::Z32),
662                Typ::U64 => (*v).try_into().ok().map(Value::U64),
663                Typ::V64 => (*v).try_into().ok().map(Value::V64),
664                Typ::I64 => (*v).try_into().ok().map(Value::I64),
665                Typ::Z64 => (*v).try_into().ok().map(Value::Z64),
666                Typ::F32 => (*v).try_into().ok().map(Value::F32),
667                Typ::F64 => (*v).try_into().ok().map(Value::F64),
668                Typ::String => {
669                    Some(Value::String(format_compact!("{}", v).as_str().into()))
670                }
671                Typ::Bool
672                | Typ::Array
673                | Typ::Map
674                | Typ::Abstract
675                | Typ::Bytes
676                | Typ::DateTime
677                | Typ::Duration
678                | Typ::Null
679                | Typ::Error => None,
680            },
681            Value::DateTime(ref v) => match typ {
682                Typ::U8 | Typ::I8 | Typ::U16 | Typ::I16 => None,
683                Typ::U32 | Typ::V32 => {
684                    let ts = v.timestamp();
685                    if ts < 0 || ts > u32::MAX as i64 {
686                        None
687                    } else {
688                        if typ == Typ::U32 {
689                            Some(Value::U32(ts as u32))
690                        } else {
691                            Some(Value::V32(ts as u32))
692                        }
693                    }
694                }
695                Typ::I32 | Typ::Z32 => {
696                    let ts = v.timestamp();
697                    if ts < i32::MIN as i64 || ts > i32::MAX as i64 {
698                        None
699                    } else {
700                        if typ == Typ::I32 {
701                            Some(Value::I32(ts as i32))
702                        } else {
703                            Some(Value::Z32(ts as i32))
704                        }
705                    }
706                }
707                Typ::U64 | Typ::V64 => {
708                    let ts = v.timestamp();
709                    if ts < 0 {
710                        None
711                    } else {
712                        if typ == Typ::U64 {
713                            Some(Value::U64(ts as u64))
714                        } else {
715                            Some(Value::V64(ts as u64))
716                        }
717                    }
718                }
719                Typ::I64 => Some(Value::I64(v.timestamp())),
720                Typ::Z64 => Some(Value::Z64(v.timestamp())),
721                Typ::F32 | Typ::F64 => {
722                    let dur = v.timestamp() as f64;
723                    let dur = dur + (v.timestamp_nanos_opt()? / 1_000_000_000) as f64;
724                    if typ == Typ::F32 {
725                        Some(Value::F32(dur as f32))
726                    } else {
727                        Some(Value::F64(dur))
728                    }
729                }
730                Typ::DateTime => Some(Value::DateTime(v.clone())),
731                Typ::Array => Some(Value::Array([self].into())),
732                Typ::Null => Some(Value::Null),
733                Typ::String => unreachable!(),
734                Typ::Decimal
735                | Typ::Duration
736                | Typ::Bool
737                | Typ::Bytes
738                | Typ::Error
739                | Typ::Map
740                | Typ::Abstract => None,
741            },
742            Value::Duration(ref d) => match typ {
743                Typ::U8 | Typ::I8 | Typ::U16 | Typ::I16 => None,
744                Typ::U32 => Some(Value::U32(d.as_secs() as u32)),
745                Typ::V32 => Some(Value::V32(d.as_secs() as u32)),
746                Typ::I32 => Some(Value::I32(d.as_secs() as i32)),
747                Typ::Z32 => Some(Value::Z32(d.as_secs() as i32)),
748                Typ::U64 => Some(Value::U64(d.as_secs() as u64)),
749                Typ::V64 => Some(Value::V64(d.as_secs() as u64)),
750                Typ::I64 => Some(Value::I64(d.as_secs() as i64)),
751                Typ::Z64 => Some(Value::Z64(d.as_secs() as i64)),
752                Typ::F32 => Some(Value::F32(d.as_secs_f32())),
753                Typ::F64 => Some(Value::F64(d.as_secs_f64())),
754                Typ::Array => Some(Value::Array([self].into())),
755                Typ::Duration => Some(Value::Duration(d.clone())),
756                Typ::Null => Some(Value::Null),
757                Typ::String => unreachable!(),
758                Typ::Decimal
759                | Typ::DateTime
760                | Typ::Bool
761                | Typ::Bytes
762                | Typ::Error
763                | Typ::Map
764                | Typ::Abstract => None,
765            },
766            Value::Bool(b) => match typ {
767                Typ::U8 => Some(Value::U8(b as u8)),
768                Typ::I8 => Some(Value::I8(b as i8)),
769                Typ::U16 => Some(Value::U16(b as u16)),
770                Typ::I16 => Some(Value::I16(b as i16)),
771                Typ::U32 => Some(Value::U32(b as u32)),
772                Typ::V32 => Some(Value::V32(b as u32)),
773                Typ::I32 => Some(Value::I32(b as i32)),
774                Typ::Z32 => Some(Value::Z32(b as i32)),
775                Typ::U64 => Some(Value::U64(b as u64)),
776                Typ::V64 => Some(Value::V64(b as u64)),
777                Typ::I64 => Some(Value::I64(b as i64)),
778                Typ::Z64 => Some(Value::Z64(b as i64)),
779                Typ::F32 => Some(Value::F32(b as u32 as f32)),
780                Typ::F64 => Some(Value::F64(b as u64 as f64)),
781                Typ::Bool => Some(self),
782                Typ::Array => Some(Value::Array([self].into())),
783                Typ::Null => Some(Value::Null),
784                Typ::String => unreachable!(),
785                Typ::Decimal
786                | Typ::DateTime
787                | Typ::Duration
788                | Typ::Bytes
789                | Typ::Error
790                | Typ::Map
791                | Typ::Abstract => None,
792            },
793            Value::Bytes(_) if typ == Typ::Bytes => Some(self),
794            Value::Bytes(_) => None,
795            Value::Error(_) => Value::Bool(false).cast(typ),
796            Value::Null if typ == Typ::Null => Some(self),
797            Value::Null => None,
798            Value::Abstract(_) if typ == Typ::Abstract => Some(self),
799            Value::Abstract(_) => None,
800        }
801    }
802
803    /// cast value directly to any type implementing `FromValue`
804    pub fn cast_to<T: FromValue + Sized>(self) -> Result<T> {
805        <T as FromValue>::from_value(self)
806    }
807
808    /// get the value as `T`, return None if the value isn't a `T`.
809    ///
810    /// don't attempt to cast.
811    pub fn get_as<T: FromValue + Sized>(self) -> Option<T> {
812        <T as FromValue>::get(self)
813    }
814
815    /// downcast an abstract value to it's concrete type
816    ///
817    /// return None if the value isn't abstract, or if `T` is not it's
818    /// concrete type.
819    pub fn downcast_ref<T: Any + Send + Sync>(&self) -> Option<&T> {
820        match self {
821            Value::Abstract(a) => a.downcast_ref::<T>(),
822            _ => None,
823        }
824    }
825
826    /// get a reference to the payload of the value without checking the tag
827    ///
828    /// If you are wrong about what kind of value you have then this
829    /// could cause undefined behavior.
830    pub unsafe fn get_as_unchecked<T>(&self) -> &T {
831        // You must run the test suite on a new platform to validate that this still works.
832        // on 64 bit platforms tag is always size 8 align 8,
833        // on 32 bit platforms tag can be align 4 or 8, but is always size 8
834        unsafe {
835            let ptr = (self as *const _ as *const u64).add(1);
836            &*(ptr as *const T)
837        }
838    }
839
840    /// construct a Value::Error from `e`
841    pub fn err<T: std::error::Error>(e: T) -> Value {
842        use std::fmt::Write;
843        let mut tmp = CompactString::new("");
844        write!(tmp, "{e}").unwrap();
845        Value::Error(Arc::new(Value::String(tmp.as_str().into())))
846    }
847
848    /// construct a Value::Error from `e`
849    pub fn error<S: Into<ArcStr>>(e: S) -> Value {
850        Value::Error(Arc::new(Value::String(e.into())))
851    }
852
853    /// return true if the value is some kind of number, otherwise
854    /// false.
855    pub fn number(&self) -> bool {
856        match self {
857            Value::U8(_)
858            | Value::I8(_)
859            | Value::U16(_)
860            | Value::I16(_)
861            | Value::U32(_)
862            | Value::V32(_)
863            | Value::I32(_)
864            | Value::Z32(_)
865            | Value::U64(_)
866            | Value::V64(_)
867            | Value::I64(_)
868            | Value::Z64(_)
869            | Value::F32(_)
870            | Value::F64(_)
871            | Value::Decimal(_) => true,
872            Value::DateTime(_)
873            | Value::Duration(_)
874            | Value::String(_)
875            | Value::Bytes(_)
876            | Value::Bool(_)
877            | Value::Null
878            | Value::Error(_)
879            | Value::Array(_)
880            | Value::Map(_)
881            | Value::Abstract(_) => false,
882        }
883    }
884
885    /// return true if the value is some kind of integer, otherwise
886    /// false.
887    pub fn integer(&self) -> bool {
888        match self {
889            Value::U8(_)
890            | Value::I8(_)
891            | Value::U16(_)
892            | Value::I16(_)
893            | Value::U32(_)
894            | Value::V32(_)
895            | Value::I32(_)
896            | Value::Z32(_)
897            | Value::U64(_)
898            | Value::V64(_)
899            | Value::I64(_)
900            | Value::Z64(_) => true,
901            Value::F32(_)
902            | Value::F64(_)
903            | Value::Decimal(_)
904            | Value::DateTime(_)
905            | Value::Duration(_)
906            | Value::String(_)
907            | Value::Bytes(_)
908            | Value::Bool(_)
909            | Value::Null
910            | Value::Error(_)
911            | Value::Array(_)
912            | Value::Map(_)
913            | Value::Abstract(_) => false,
914        }
915    }
916
917    /// return an iterator that will perform a depth first traversal
918    /// of the specified value. All array elements will be flattened
919    /// into non array values.
920    pub fn flatten(self) -> impl Iterator<Item = Value> {
921        use utils::Either;
922        match self {
923            Value::Array(elts) => {
924                let mut stack: SmallVec<[(ValArray, usize); 8]> = SmallVec::new();
925                stack.push((elts, 0));
926                Either::Left(iter::from_fn(move || loop {
927                    match stack.last_mut() {
928                        None => break None,
929                        Some((elts, pos)) => {
930                            if *pos >= elts.len() {
931                                stack.pop();
932                            } else {
933                                match &elts[*pos] {
934                                    Value::Array(elts) => {
935                                        *pos += 1;
936                                        let elts = elts.clone();
937                                        stack.push((elts, 0));
938                                    }
939                                    val => {
940                                        *pos += 1;
941                                        break Some(val.clone());
942                                    }
943                                }
944                            }
945                        }
946                    }
947                }))
948            }
949            val => Either::Right(iter::once(val)),
950        }
951    }
952}