netidx_value/
typ.rs

1use crate::Value;
2use anyhow::{anyhow, bail};
3use arcstr::ArcStr;
4use chrono::prelude::*;
5use enumflags2::{bitflags, BitFlags};
6use rust_decimal::Decimal;
7use serde::{Deserialize, Serialize};
8use std::{
9    cmp::{PartialEq, PartialOrd},
10    fmt, mem, result,
11    str::FromStr,
12};
13use triomphe::Arc;
14
15// Each Typ corresponds directly to the tag of a Value, the bits are
16// the same, and they can be used interchangeably.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
18#[repr(u32)]
19#[bitflags]
20pub enum Typ {
21    U32 = 0x0000_0001,
22    V32 = 0x0000_0002,
23    I32 = 0x0000_0004,
24    Z32 = 0x0000_0008,
25    U64 = 0x0000_0010,
26    V64 = 0x0000_0020,
27    I64 = 0x0000_0040,
28    Z64 = 0x0000_0080,
29    F32 = 0x0000_0100,
30    F64 = 0x0000_0200,
31    Bool = 0x0000_0400,
32    Null = 0x0000_0800,
33    String = 0x8000_0000,
34    Bytes = 0x4000_0000,
35    Error = 0x2000_0000,
36    Array = 0x1000_0000,
37    Map = 0x0800_0000,
38    Decimal = 0x0400_0000,
39    DateTime = 0x0200_0000,
40    Duration = 0x0100_0000,
41}
42
43impl Typ {
44    pub fn parse(&self, s: &str) -> anyhow::Result<Value> {
45        match self {
46            Typ::U32 => Ok(Value::U32(s.parse::<u32>()?)),
47            Typ::V32 => Ok(Value::V32(s.parse::<u32>()?)),
48            Typ::I32 => Ok(Value::I32(s.parse::<i32>()?)),
49            Typ::Z32 => Ok(Value::Z32(s.parse::<i32>()?)),
50            Typ::U64 => Ok(Value::U64(s.parse::<u64>()?)),
51            Typ::V64 => Ok(Value::V64(s.parse::<u64>()?)),
52            Typ::I64 => Ok(Value::I64(s.parse::<i64>()?)),
53            Typ::Z64 => Ok(Value::Z64(s.parse::<i64>()?)),
54            Typ::F32 => Ok(Value::F32(s.parse::<f32>()?)),
55            Typ::F64 => Ok(Value::F64(s.parse::<f64>()?)),
56            Typ::Decimal => Ok(Value::Decimal(Arc::new(s.parse::<Decimal>()?))),
57            Typ::DateTime => Ok(Value::DateTime(Arc::new(DateTime::from_str(s)?))),
58            Typ::Duration => {
59                let mut tmp = String::from("duration:");
60                tmp.push_str(s);
61                Ok(tmp.parse::<Value>()?)
62            }
63            Typ::Bool => Ok(Value::Bool(s.parse::<bool>()?)),
64            Typ::String => Ok(Value::String(ArcStr::from(s))),
65            Typ::Bytes => {
66                let mut tmp = String::from("bytes:");
67                tmp.push_str(s);
68                Ok(tmp.parse::<Value>()?)
69            }
70            Typ::Error => Ok(s.parse::<Value>()?),
71            Typ::Array => Ok(s.parse::<Value>()?),
72            Typ::Map => Ok(s.parse::<Value>()?),
73            Typ::Null => {
74                if s.trim() == "null" {
75                    Ok(Value::Null)
76                } else {
77                    bail!("expected null")
78                }
79            }
80        }
81    }
82
83    pub fn name(&self) -> &'static str {
84        match self {
85            Typ::U32 => "u32",
86            Typ::V32 => "v32",
87            Typ::I32 => "i32",
88            Typ::Z32 => "z32",
89            Typ::U64 => "u64",
90            Typ::I64 => "i64",
91            Typ::V64 => "v64",
92            Typ::Z64 => "z64",
93            Typ::F32 => "f32",
94            Typ::F64 => "f64",
95            Typ::Decimal => "decimal",
96            Typ::DateTime => "datetime",
97            Typ::Duration => "duration",
98            Typ::Bool => "bool",
99            Typ::String => "string",
100            Typ::Bytes => "bytes",
101            Typ::Error => "error",
102            Typ::Array => "array",
103            Typ::Map => "map",
104            Typ::Null => "null",
105        }
106    }
107
108    pub fn get(v: &Value) -> Self {
109        // safe because we are repr(u32) and because the tags are the
110        // same between Typ and Value
111        unsafe { mem::transmute::<u32, Typ>(v.discriminant()) }
112    }
113
114    pub fn any() -> BitFlags<Typ> {
115        BitFlags::all()
116    }
117
118    pub fn number() -> BitFlags<Typ> {
119        Typ::U32
120            | Typ::V32
121            | Typ::I32
122            | Typ::Z32
123            | Typ::U64
124            | Typ::V64
125            | Typ::I64
126            | Typ::Z64
127            | Typ::F32
128            | Typ::F64
129            | Typ::Decimal
130    }
131
132    pub fn is_number(&self) -> bool {
133        Self::number().contains(*self)
134    }
135
136    pub fn integer() -> BitFlags<Typ> {
137        Typ::U32
138            | Typ::V32
139            | Typ::I32
140            | Typ::Z32
141            | Typ::U64
142            | Typ::V64
143            | Typ::I64
144            | Typ::Z64
145    }
146
147    pub fn is_integer(&self) -> bool {
148        Self::integer().contains(*self)
149    }
150
151    pub fn signed_integer() -> BitFlags<Typ> {
152        Typ::I32 | Typ::Z32 | Typ::I64 | Typ::Z64
153    }
154
155    pub fn is_signed_integer(&self) -> bool {
156        Self::signed_integer().contains(*self)
157    }
158
159    pub fn unsigned_integer() -> BitFlags<Typ> {
160        Typ::U32 | Typ::V32 | Typ::U64 | Typ::V64
161    }
162
163    pub fn is_unsigned_integer(&self) -> bool {
164        Self::unsigned_integer().contains(*self)
165    }
166
167    pub fn float() -> BitFlags<Typ> {
168        Typ::F32 | Typ::F64
169    }
170
171    pub fn real() -> BitFlags<Typ> {
172        Typ::F32 | Typ::F64 | Typ::Decimal
173    }
174
175    pub fn is_real(&self) -> bool {
176        Self::real().contains(*self)
177    }
178}
179
180impl FromStr for Typ {
181    type Err = anyhow::Error;
182
183    fn from_str(s: &str) -> result::Result<Self, Self::Err> {
184        match s {
185            "U32" | "u32" => Ok(Typ::U32),
186            "V32" | "v32" => Ok(Typ::V32),
187            "I32" | "i32" => Ok(Typ::I32),
188            "Z32" | "z32" => Ok(Typ::Z32),
189            "U64" | "u64" => Ok(Typ::U64),
190            "V64" | "v64" => Ok(Typ::V64),
191            "I64" | "i64" => Ok(Typ::I64),
192            "Z64" | "z64" => Ok(Typ::Z64),
193            "F32" | "f32" => Ok(Typ::F32),
194            "F64" | "f64" => Ok(Typ::F64),
195            "Decimal" | "decimal" => Ok(Typ::Decimal),
196            "DateTime" | "datetime" => Ok(Typ::DateTime),
197            "Duration" | "duration" => Ok(Typ::Duration),
198            "Bool" | "bool" => Ok(Typ::Bool),
199            "String" | "string" => Ok(Typ::String),
200            "Bytes" | "bytes" => Ok(Typ::Bytes),
201            "Error" | "error" => Ok(Typ::Error),
202            "Array" | "array" => Ok(Typ::Array),
203            "Map" | "map" => Ok(Typ::Map),
204            "Null" | "null" => Ok(Typ::Null),
205            s => Err(anyhow!(
206                "invalid type, {}, valid types: u32, i32, u64, i64, f32, f64, bool, string, bytes, error, array, map, null", s))
207        }
208    }
209}
210
211impl fmt::Display for Typ {
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        write!(f, "{}", self.name())
214    }
215}