Skip to main content

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