eva_common/value/
mod.rs

1//! Based on https://github.com/arcnmx/serde-value
2#![allow(
3    clippy::cast_possible_truncation,
4    clippy::cast_precision_loss,
5    clippy::cast_sign_loss,
6    clippy::cast_possible_wrap,
7    clippy::cast_lossless
8)]
9
10use crate::{EResult, Error};
11use ordered_float::OrderedFloat;
12use rust_decimal::prelude::*;
13use serde::{Deserialize, Deserializer, Serialize};
14use std::cmp::Ordering;
15use std::collections::{BTreeMap, HashSet};
16use std::convert::AsRef;
17use std::convert::{TryFrom, TryInto};
18use std::fmt;
19use std::hash::{BuildHasher, Hash, Hasher};
20use std::iter::FromIterator;
21#[cfg(feature = "extended-value")]
22use std::path::Path;
23#[cfg(feature = "extended-value")]
24use std::time::Duration;
25
26pub use de::*;
27pub use ser::*;
28
29//pub use ser::SerializerError;
30//pub use de::DeserializerError;
31
32mod de;
33mod index;
34mod ser;
35
36pub use index::{Index, IndexSlice};
37
38impl From<de::DeserializerError> for Error {
39    fn from(err: de::DeserializerError) -> Error {
40        Error::invalid_data(err)
41    }
42}
43
44impl From<ser::SerializerError> for Error {
45    fn from(err: ser::SerializerError) -> Error {
46        Error::invalid_data(err)
47    }
48}
49
50const ERR_INVALID_VALUE: &str = "Invalid value";
51const ERR_INVALID_BOOLEAN_VALUE: &str = "Invalid boolean value";
52const ERR_EXPECTED_VEC_OR_STRING: &str = "Expected Vec or String";
53const ERR_UNABLE_PARSE_FLOAT: &str = "Unable to parse float";
54const ERR_UNABLE_CONVERT_FLOAT: &str = "Unable to convert float";
55const ERR_TOO_BIG_NUMBER: &str = "Value too big";
56const ERR_TOO_SMALL_NUMBER: &str = "Value too small";
57
58macro_rules! float_from_bool {
59    ($v: expr) => {
60        if $v {
61            1.0
62        } else {
63            0.0
64        }
65    };
66}
67
68#[allow(clippy::module_name_repetitions)]
69#[derive(Debug, Serialize, Clone, Eq, PartialEq, Default)]
70#[serde(untagged)]
71pub enum ValueOptionOwned {
72    #[default]
73    No,
74    Value(Value),
75}
76
77impl ValueOptionOwned {
78    pub fn is_none(&self) -> bool {
79        matches!(self, ValueOptionOwned::No)
80    }
81
82    pub fn is_some(&self) -> bool {
83        !matches!(self, ValueOptionOwned::No)
84    }
85
86    pub fn as_ref(&self) -> Option<&Value> {
87        match self {
88            ValueOptionOwned::No => None,
89            ValueOptionOwned::Value(ref v) => Some(v),
90        }
91    }
92}
93
94impl From<ValueOptionOwned> for Option<Value> {
95    fn from(vo: ValueOptionOwned) -> Self {
96        match vo {
97            ValueOptionOwned::No => None,
98            ValueOptionOwned::Value(v) => Some(v),
99        }
100    }
101}
102
103impl From<Option<Value>> for ValueOptionOwned {
104    fn from(v: Option<Value>) -> Self {
105        if let Some(val) = v {
106            ValueOptionOwned::Value(val)
107        } else {
108            ValueOptionOwned::No
109        }
110    }
111}
112
113#[allow(clippy::module_name_repetitions)]
114#[derive(Debug, Serialize, Clone, Eq, PartialEq, Default)]
115#[serde(untagged)]
116pub enum ValueOption<'a> {
117    #[default]
118    No,
119    Value(&'a Value),
120}
121
122impl ValueOption<'_> {
123    pub fn is_none(&self) -> bool {
124        matches!(self, ValueOption::No)
125    }
126
127    pub fn is_some(&self) -> bool {
128        !matches!(self, ValueOption::No)
129    }
130}
131
132impl<'de> Deserialize<'de> for ValueOptionOwned {
133    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
134    where
135        D: Deserializer<'de>,
136    {
137        Ok(ValueOptionOwned::Value(Value::deserialize(deserializer)?))
138    }
139}
140
141#[cfg(feature = "time")]
142#[inline]
143fn parse_time_frame(s: &str) -> Option<f64> {
144    if s.len() < 2 {
145        None
146    } else if let Ok(v) = s[..s.len() - 1].parse::<f64>() {
147        match &s[s.len() - 1..] {
148            "S" => Some(v),
149            "T" => Some(v * 60.0),
150            "H" => Some(v * 3_600.0),
151            "D" => Some(v * 86_400.0),
152            "W" => Some(v * 604_800.0),
153            _ => None,
154        }
155    } else {
156        None
157    }
158}
159
160const ERR_INVALID_JSON_PATH: &str = "invalid JSON path, does not start with $.";
161const ERR_UNSUPPORTED_JSON_PATH_DOUBLE_DOT: &str = "unsupported JSON path (..)";
162
163fn value_jp_lookup<'a>(
164    value: &'a Value,
165    sp: &mut std::str::Split<'_, char>,
166    allow_empty: bool,
167) -> EResult<Option<&'a Value>> {
168    macro_rules! abort {
169        () => {
170            return Ok(None)
171        };
172    }
173    if let Some(x) = sp.next() {
174        if x.is_empty() {
175            if allow_empty {
176                return value_jp_lookup(value, sp, false);
177            }
178            return Err(Error::invalid_params(ERR_UNSUPPORTED_JSON_PATH_DOUBLE_DOT));
179        }
180        let (field, idx) = if x.ends_with(']') {
181            let mut spx = x.rsplitn(2, '[');
182            let idx_s = spx.next().unwrap();
183            let idx: usize = idx_s[..idx_s.len() - 1]
184                .parse()
185                .map_err(|e| Error::invalid_params(format!("invalid path index: {} ({})", x, e)))?;
186            let field = spx
187                .next()
188                .ok_or_else(|| Error::invalid_params(format!("invalid path: {}", x)))?;
189            (if field.is_empty() { None } else { Some(field) }, Some(idx))
190        } else {
191            (Some(x), None)
192        };
193        let field_val = if let Some(f) = field {
194            let Value::Map(m) = value else { abort!() };
195            let Some(v) = m.get(&Value::String(f.to_owned())) else {
196                abort!()
197            };
198            v
199        } else {
200            value
201        };
202        let field_indexed = if let Some(i) = idx {
203            let Value::Seq(s) = field_val else { abort!() };
204            let Some(v) = s.get(i) else { abort!() };
205            v
206        } else {
207            field_val
208        };
209        return value_jp_lookup(field_indexed, sp, true);
210    }
211    Ok(Some(value))
212}
213
214fn value_jp_insert(
215    source: &mut Value,
216    sp: &mut std::str::Split<'_, char>,
217    value: Value,
218    allow_empty: bool,
219) -> EResult<()> {
220    macro_rules! abort {
221        ($err:expr) => {
222            return Err(Error::invalid_data_static($err))
223        };
224    }
225    if let Some(x) = sp.next() {
226        if x.is_empty() {
227            if allow_empty {
228                return value_jp_insert(source, sp, value, false);
229            }
230            return Err(Error::invalid_params(ERR_UNSUPPORTED_JSON_PATH_DOUBLE_DOT));
231        }
232        let (field, idx) = if x.ends_with(']') {
233            let mut spx = x.rsplitn(2, '[');
234            let idx_s = spx.next().unwrap();
235            let idx: usize = idx_s[..idx_s.len() - 1]
236                .parse()
237                .map_err(|e| Error::invalid_params(format!("invalid path index: {} ({})", x, e)))?;
238            let field = spx
239                .next()
240                .ok_or_else(|| Error::invalid_params(format!("invalid path: {}", x)))?;
241            (if field.is_empty() { None } else { Some(field) }, Some(idx))
242        } else {
243            (Some(x), None)
244        };
245        let field_val = if let Some(f) = field {
246            if *source == Value::Unit {
247                *source = Value::Map(<_>::default());
248            }
249            let Value::Map(m) = source else {
250                abort!("source is not a map")
251            };
252            m.entry(Value::String(f.to_owned())).or_insert(Value::Unit)
253        } else {
254            source
255        };
256        let field_indexed = if let Some(i) = idx {
257            if *field_val == Value::Unit {
258                *field_val = Value::Seq(<_>::default());
259            }
260            let Value::Seq(s) = field_val else {
261                abort!("source is not a sequence")
262            };
263            if s.len() < i + 1 {
264                s.resize(i + 1, Value::Unit);
265            }
266            s.get_mut(i).unwrap()
267        } else {
268            field_val
269        };
270        return value_jp_insert(field_indexed, sp, value, true);
271    }
272    *source = value;
273    Ok(())
274}
275
276#[inline]
277fn parse_jp(path: &str) -> EResult<std::str::Split<'_, char>> {
278    if let Some(p) = path.strip_prefix("$.") {
279        Ok(p.split('.'))
280    } else {
281        Err(Error::invalid_params(ERR_INVALID_JSON_PATH))
282    }
283}
284
285#[derive(Clone, Debug, Default)]
286pub enum Value {
287    Bool(bool),
288
289    U8(u8),
290    U16(u16),
291    U32(u32),
292    U64(u64),
293
294    I8(i8),
295    I16(i16),
296    I32(i32),
297    I64(i64),
298
299    F32(f32),
300    F64(f64),
301
302    Char(char),
303    String(String),
304
305    #[default]
306    Unit,
307    Option(Option<Box<Value>>),
308    Newtype(Box<Value>),
309    Seq(Vec<Value>),
310    Map(BTreeMap<Value, Value>),
311    Bytes(Vec<u8>),
312}
313
314impl fmt::Display for Value {
315    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316        match self {
317            Value::Bool(v) => write!(f, "{}", v),
318            Value::U8(v) => write!(f, "{}", v),
319            Value::U16(v) => write!(f, "{}", v),
320            Value::U32(v) => write!(f, "{}", v),
321            Value::U64(v) => write!(f, "{}", v),
322            Value::I8(v) => write!(f, "{}", v),
323            Value::I16(v) => write!(f, "{}", v),
324            Value::I32(v) => write!(f, "{}", v),
325            Value::I64(v) => write!(f, "{}", v),
326            Value::F32(v) => write!(f, "{}", v),
327            Value::F64(v) => write!(f, "{}", v),
328            Value::Char(v) => write!(f, "{}", v),
329            Value::String(ref v) => write!(f, "{}", v),
330            Value::Unit => write!(f, ""),
331            Value::Option(ref v) => {
332                if let Some(val) = v {
333                    write!(f, "{}", val)
334                } else {
335                    write!(f, "")
336                }
337            }
338            Value::Newtype(ref v) => write!(f, "{}", v),
339            Value::Seq(ref v) => write!(f, "{:?}", v),
340            Value::Map(ref v) => write!(f, "{:?}", v),
341            Value::Bytes(ref v) => write!(f, "{:?}", v),
342        }
343    }
344}
345
346impl Hash for Value {
347    fn hash<H>(&self, hasher: &mut H)
348    where
349        H: Hasher,
350    {
351        self.discriminant().hash(hasher);
352        match *self {
353            Value::Bool(v) => v.hash(hasher),
354            Value::U8(v) => v.hash(hasher),
355            Value::U16(v) => v.hash(hasher),
356            Value::U32(v) => v.hash(hasher),
357            Value::U64(v) => v.hash(hasher),
358            Value::I8(v) => v.hash(hasher),
359            Value::I16(v) => v.hash(hasher),
360            Value::I32(v) => v.hash(hasher),
361            Value::I64(v) => v.hash(hasher),
362            Value::F32(v) => OrderedFloat(v).hash(hasher),
363            Value::F64(v) => OrderedFloat(v).hash(hasher),
364            Value::Char(v) => v.hash(hasher),
365            Value::String(ref v) => v.hash(hasher),
366            Value::Unit => 0_u8.hash(hasher),
367            Value::Option(ref v) => v.hash(hasher),
368            Value::Newtype(ref v) => v.hash(hasher),
369            Value::Seq(ref v) => v.hash(hasher),
370            Value::Map(ref v) => v.hash(hasher),
371            Value::Bytes(ref v) => v.hash(hasher),
372        }
373    }
374}
375
376macro_rules! cmp_number {
377    ($n: expr, $v: expr, $t: ty) => {
378        if $v.is_numeric_type() {
379            <$t>::try_from($v).map_or(false, |v| $n == v)
380        } else {
381            false
382        }
383    };
384}
385
386impl PartialEq for Value {
387    fn eq(&self, rhs: &Self) -> bool {
388        match (self, rhs) {
389            (&Value::Bool(v0), &Value::Bool(v1)) if v0 == v1 => true,
390            (v0, &Value::F32(v1)) => cmp_number!(v1, v0, f32),
391            (v0, &Value::F64(v1)) => cmp_number!(v1, v0, f64),
392            (&Value::U8(v0), v1) => cmp_number!(v0, v1, u8),
393            (&Value::U16(v0), v1) => cmp_number!(v0, v1, u16),
394            (&Value::U32(v0), v1) => cmp_number!(v0, v1, u32),
395            (&Value::U64(v0), v1) => cmp_number!(v0, v1, u64),
396            (&Value::I8(v0), v1) => cmp_number!(v0, v1, i8),
397            (&Value::I16(v0), v1) => cmp_number!(v0, v1, i16),
398            (&Value::I32(v0), v1) => cmp_number!(v0, v1, i32),
399            (&Value::I64(v0), v1) => cmp_number!(v0, v1, i64),
400            (&Value::F32(v0), v1) => cmp_number!(v0, v1, f32),
401            (&Value::F64(v0), v1) => cmp_number!(v0, v1, f64),
402            (&Value::Char(v0), &Value::Char(v1)) if v0 == v1 => true,
403            (Value::String(v0), Value::String(v1)) if v0 == v1 => true,
404            (&Value::Unit, &Value::Unit) => true,
405            (Value::Option(v0), Value::Option(v1)) if v0 == v1 => true,
406            (Value::Newtype(v0), Value::Newtype(v1)) if v0 == v1 => true,
407            (Value::Seq(v0), Value::Seq(v1)) if v0 == v1 => true,
408            (Value::Map(v0), Value::Map(v1)) if v0 == v1 => true,
409            (Value::Bytes(v0), Value::Bytes(v1)) if v0 == v1 => true,
410            _ => false,
411        }
412    }
413}
414
415impl Ord for Value {
416    fn cmp(&self, rhs: &Self) -> Ordering {
417        match (self, rhs) {
418            (Value::Bool(v0), Value::Bool(v1)) => v0.cmp(v1),
419            (Value::U8(v0), Value::U8(v1)) => v0.cmp(v1),
420            (Value::U16(v0), Value::U16(v1)) => v0.cmp(v1),
421            (Value::U32(v0), Value::U32(v1)) => v0.cmp(v1),
422            (Value::U64(v0), Value::U64(v1)) => v0.cmp(v1),
423            (Value::I8(v0), Value::I8(v1)) => v0.cmp(v1),
424            (Value::I16(v0), Value::I16(v1)) => v0.cmp(v1),
425            (Value::I32(v0), Value::I32(v1)) => v0.cmp(v1),
426            (Value::I64(v0), Value::I64(v1)) => v0.cmp(v1),
427            (&Value::F32(v0), &Value::F32(v1)) => OrderedFloat(v0).cmp(&OrderedFloat(v1)),
428            (&Value::F64(v0), &Value::F64(v1)) => OrderedFloat(v0).cmp(&OrderedFloat(v1)),
429            (Value::Char(v0), Value::Char(v1)) => v0.cmp(v1),
430            (Value::String(v0), Value::String(v1)) => v0.cmp(v1),
431            (&Value::Unit, &Value::Unit) => Ordering::Equal,
432            (Value::Option(v0), Value::Option(v1)) => v0.cmp(v1),
433            (Value::Newtype(v0), Value::Newtype(v1)) => v0.cmp(v1),
434            (Value::Seq(ref v0), Value::Seq(v1)) => v0.cmp(v1),
435            (Value::Map(v0), Value::Map(v1)) => v0.cmp(v1),
436            (Value::Bytes(v0), Value::Bytes(v1)) => v0.cmp(v1),
437            (v0, v1) => v0.discriminant().cmp(&v1.discriminant()),
438        }
439    }
440}
441
442fn strip_bytes_rec(value: Value) -> Value {
443    if let Value::Bytes(_) = value {
444        Value::String("<binary>".to_owned())
445    } else if let Value::Seq(s) = value {
446        let v: Vec<Value> = s.into_iter().map(strip_bytes_rec).collect();
447        Value::Seq(v)
448    } else if let Value::Map(m) = value {
449        let mut result = BTreeMap::new();
450        for (k, v) in m {
451            result.insert(k, strip_bytes_rec(v));
452        }
453        Value::Map(result)
454    } else {
455        value
456    }
457}
458
459fn flat_seq_value_rec(v: Value, result: &mut Vec<Value>) {
460    if let Value::Seq(s) = v {
461        for val in s {
462            flat_seq_value_rec(val, result);
463        }
464    } else {
465        result.push(v);
466    }
467}
468
469impl Value {
470    pub fn jp_lookup<'a>(&'a self, path: &str) -> EResult<Option<&'a Value>> {
471        let mut sp = parse_jp(path)?;
472        value_jp_lookup(self, &mut sp, true)
473    }
474    pub fn jp_insert(&mut self, path: &str, value: Value) -> EResult<()> {
475        let mut sp = parse_jp(path)?;
476        value_jp_insert(self, &mut sp, value, true)
477    }
478    pub fn into_seq_flatten(self) -> Value {
479        let result = if self.is_seq() {
480            let mut result = Vec::new();
481            flat_seq_value_rec(self, &mut result);
482            result
483        } else {
484            vec![self]
485        };
486        Value::Seq(result)
487    }
488    pub fn into_seq_reshaped(self, dimensions: &[usize]) -> Value {
489        let default = match self {
490            Value::Bool(_) => Value::Bool(false),
491            Value::String(_) => Value::String(String::new()),
492            Value::Unit => Value::Unit,
493            _ => Value::U8(0),
494        };
495        let Value::Seq(mut v) = self.into_seq_flatten() else {
496            return Value::Unit;
497        };
498        if dimensions.is_empty() {
499            return Value::Seq(v);
500        }
501        let mut len = 1;
502        for d in dimensions {
503            len *= d;
504        }
505        v.resize(len, default);
506        for d in dimensions[1..].iter().rev() {
507            let d = *d;
508            let len = v.len();
509            let mut result: Vec<Value> = Vec::with_capacity(len / d);
510            for _ in (0..len).step_by(d) {
511                let tail = v.split_off(d);
512                result.push(Value::Seq(v));
513                v = tail;
514            }
515            v = result;
516        }
517        Value::Seq(v)
518    }
519    #[inline]
520    pub fn get_by_index(&self, idx: &Index) -> Option<&Value> {
521        self.get_by_index_slice(idx.as_slice())
522    }
523    fn get_by_index_slice(&self, idx: IndexSlice<'_>) -> Option<&Value> {
524        if idx.0.is_empty() {
525            return Some(self);
526        }
527        if let Value::Seq(ref s) = self {
528            if let Some(s) = s.get(idx.0[0]) {
529                return s.get_by_index_slice(IndexSlice(&idx.0[1..]));
530            }
531        } else if idx.0.len() == 1 && idx.0[0] == 0 {
532            return Some(self);
533        }
534        None
535    }
536
537    /// Rounds value to digits after comma, if the value is float
538    #[allow(clippy::cast_possible_truncation)]
539    #[allow(clippy::cast_sign_loss)]
540    pub fn rounded(self, precision: Option<u32>) -> EResult<Value> {
541        if let Some(precs) = precision {
542            if let Value::F64(vf) = self {
543                if precs > 0 {
544                    let d = Decimal::from_f64_retain(vf)
545                        .ok_or_else(|| Error::invalid_data_static(ERR_UNABLE_PARSE_FLOAT))?;
546                    let rounded = d.round_dp(precs);
547                    return Ok(Value::F64(rounded.to_f64().ok_or_else(|| {
548                        Error::invalid_data_static(ERR_UNABLE_CONVERT_FLOAT)
549                    })?));
550                }
551                return Ok(Value::U64(vf.round() as u64));
552            }
553            if let Value::F32(vf) = self {
554                if precs > 0 {
555                    let d = Decimal::from_f32_retain(vf)
556                        .ok_or_else(|| Error::invalid_data_static(ERR_UNABLE_PARSE_FLOAT))?;
557                    let rounded = d.round_dp(precs);
558                    return Ok(Value::F32(rounded.to_f32().ok_or_else(|| {
559                        Error::invalid_data_static(ERR_UNABLE_CONVERT_FLOAT)
560                    })?));
561                }
562                return Ok(Value::U32(vf.round() as u32));
563            }
564        }
565        Ok(self)
566    }
567
568    pub fn to_no_bytes(self) -> Value {
569        strip_bytes_rec(self)
570    }
571
572    #[cfg(feature = "time")]
573    #[inline]
574    /// Tries to convert Value to f64 timestamp
575    ///
576    /// Valid options are:
577    ///
578    /// number - timestamp as-is
579    /// time frame as N<S|T|H|D|W>, e.g. 5T for 5 minutes: now - time frame
580    /// other string - tries to parse the string into date/time
581    pub fn as_timestamp(&self) -> EResult<f64> {
582        self.as_ts(true)
583    }
584
585    #[cfg(feature = "time")]
586    #[inline]
587    /// Same as as_timestamp() but time frames are added to now
588    pub fn as_future_timestamp(&self) -> EResult<f64> {
589        self.as_ts(false)
590    }
591
592    #[cfg(feature = "time")]
593    #[allow(clippy::cast_precision_loss)]
594    fn as_ts(&self, tf_past: bool) -> EResult<f64> {
595        if let Ok(v) = f64::try_from(self) {
596            Ok(v)
597        } else if let Value::String(s) = self {
598            if let Some(v) = parse_time_frame(s) {
599                let now = crate::time::now_ns_float();
600                Ok(if tf_past { now - v } else { now + v })
601            } else {
602                let d = dateparser::parse(s).map_err(Error::invalid_data)?;
603                let timestamp =
604                    d.timestamp() as f64 + f64::from(d.timestamp_subsec_nanos()) / 1_000_000_000.0;
605                Ok(timestamp)
606            }
607        } else {
608            Err(Error::invalid_data_static("unsupported date/time format"))
609        }
610    }
611
612    pub fn to_alphanumeric_string(self) -> EResult<String> {
613        match self {
614            Value::Bool(v) => Ok(v.to_string()),
615            Value::U8(v) => Ok(v.to_string()),
616            Value::U16(v) => Ok(v.to_string()),
617            Value::U32(v) => Ok(v.to_string()),
618            Value::U64(v) => Ok(v.to_string()),
619            Value::I8(v) => Ok(v.to_string()),
620            Value::I16(v) => Ok(v.to_string()),
621            Value::I32(v) => Ok(v.to_string()),
622            Value::I64(v) => Ok(v.to_string()),
623            Value::F32(v) => Ok(v.to_string()),
624            Value::F64(v) => Ok(v.to_string()),
625            Value::Char(v) => Ok(v.to_string()),
626            Value::String(v) => {
627                for c in v.chars() {
628                    if !c.is_alphanumeric() {
629                        return Err(Error::invalid_params(format!("invalid symbols in {}", v)));
630                    }
631                }
632                Ok(v)
633            }
634            Value::Unit => Ok("null".to_owned()),
635            _ => Err(Error::invalid_data(format!(
636                "unable to get string from {:?}",
637                self
638            ))),
639        }
640    }
641
642    pub fn to_string_or_pack(self) -> EResult<String> {
643        match self {
644            Value::U8(v) => Ok(v.to_string()),
645            Value::U16(v) => Ok(v.to_string()),
646            Value::U32(v) => Ok(v.to_string()),
647            Value::U64(v) => Ok(v.to_string()),
648            Value::I8(v) => Ok(v.to_string()),
649            Value::I16(v) => Ok(v.to_string()),
650            Value::I32(v) => Ok(v.to_string()),
651            Value::I64(v) => Ok(v.to_string()),
652            Value::F32(v) => Ok(v.to_string()),
653            Value::F64(v) => Ok(v.to_string()),
654            Value::Char(v) => Ok(v.to_string()),
655            Value::String(v) => Ok(v),
656            _ => Ok(format!("!!{}", serde_json::to_string(&self)?)),
657        }
658    }
659
660    pub fn unpack(self) -> EResult<Self> {
661        if let Value::String(ref v) = self {
662            if let Some(s) = v.strip_prefix("!!") {
663                return serde_json::from_str(s).map_err(Into::into);
664            }
665        }
666        Ok(self)
667    }
668
669    fn discriminant(&self) -> usize {
670        match *self {
671            Value::Bool(..) => 0,
672            Value::U8(..) => 1,
673            Value::U16(..) => 2,
674            Value::U32(..) => 3,
675            Value::U64(..) => 4,
676            Value::I8(..) => 5,
677            Value::I16(..) => 6,
678            Value::I32(..) => 7,
679            Value::I64(..) => 8,
680            Value::F32(..) => 9,
681            Value::F64(..) => 10,
682            Value::Char(..) => 11,
683            Value::String(..) => 12,
684            Value::Unit => 13,
685            Value::Option(..) => 14,
686            Value::Newtype(..) => 15,
687            Value::Seq(..) => 16,
688            Value::Map(..) => 17,
689            Value::Bytes(..) => 18,
690        }
691    }
692
693    fn unexpected(&self) -> serde::de::Unexpected {
694        match *self {
695            Value::Bool(b) => serde::de::Unexpected::Bool(b),
696            Value::U8(n) => serde::de::Unexpected::Unsigned(u64::from(n)),
697            Value::U16(n) => serde::de::Unexpected::Unsigned(u64::from(n)),
698            Value::U32(n) => serde::de::Unexpected::Unsigned(u64::from(n)),
699            Value::U64(n) => serde::de::Unexpected::Unsigned(n),
700            Value::I8(n) => serde::de::Unexpected::Signed(i64::from(n)),
701            Value::I16(n) => serde::de::Unexpected::Signed(i64::from(n)),
702            Value::I32(n) => serde::de::Unexpected::Signed(i64::from(n)),
703            Value::I64(n) => serde::de::Unexpected::Signed(n),
704            Value::F32(n) => serde::de::Unexpected::Float(f64::from(n)),
705            Value::F64(n) => serde::de::Unexpected::Float(n),
706            Value::Char(c) => serde::de::Unexpected::Char(c),
707            Value::String(ref s) => serde::de::Unexpected::Str(s),
708            Value::Unit => serde::de::Unexpected::Unit,
709            Value::Option(_) => serde::de::Unexpected::Option,
710            Value::Newtype(_) => serde::de::Unexpected::NewtypeStruct,
711            Value::Seq(_) => serde::de::Unexpected::Seq,
712            Value::Map(_) => serde::de::Unexpected::Map,
713            Value::Bytes(ref b) => serde::de::Unexpected::Bytes(b),
714        }
715    }
716
717    pub fn deserialize_into<'de, T: Deserialize<'de>>(self) -> Result<T, DeserializerError> {
718        T::deserialize(self)
719    }
720    pub fn is_empty(&self) -> bool {
721        match self {
722            Value::Unit => true,
723            Value::Option(v) => v.is_none(),
724            Value::String(s) => s.is_empty(),
725            _ => false,
726        }
727    }
728    #[inline]
729    pub fn is_unit(&self) -> bool {
730        *self == Value::Unit
731    }
732    pub fn is_numeric_type(&self) -> bool {
733        matches!(
734            self,
735            Value::U8(_)
736                | Value::U16(_)
737                | Value::U32(_)
738                | Value::U64(_)
739                | Value::I8(_)
740                | Value::I16(_)
741                | Value::I32(_)
742                | Value::I64(_)
743                | Value::F32(_)
744                | Value::F64(_)
745        )
746    }
747    pub fn is_numeric(&self) -> bool {
748        match self {
749            Value::U8(_)
750            | Value::U16(_)
751            | Value::U32(_)
752            | Value::U64(_)
753            | Value::I8(_)
754            | Value::I16(_)
755            | Value::I32(_)
756            | Value::I64(_)
757            | Value::F32(_)
758            | Value::F64(_) => true,
759            Value::String(v) => v.parse::<f64>().is_ok() || v.parse::<i128>().is_ok(),
760            _ => false,
761        }
762    }
763    pub fn is_seq(&self) -> bool {
764        matches!(self, Value::Seq(_))
765    }
766    pub fn is_map(&self) -> bool {
767        matches!(self, Value::Map(_))
768    }
769    #[cfg(feature = "extended-value")]
770    pub async fn extend(self, timeout: Duration, base: &Path) -> EResult<Value> {
771        let op = crate::op::Op::new(timeout);
772        extend_value(self, &op, base).await
773    }
774}
775
776#[cfg(feature = "extended-value")]
777#[async_recursion::async_recursion]
778async fn extend_value(value: Value, op: &crate::op::Op, base: &Path) -> EResult<Value> {
779    match value {
780        Value::String(s) => Ok(extend_string_value(s, op, base).await?),
781        Value::Seq(s) => {
782            let mut result = Vec::with_capacity(s.len());
783            for val in s {
784                result.push(extend_value(val, op, base).await?);
785            }
786            Ok(Value::Seq(result))
787        }
788        Value::Map(m) => {
789            let mut result = BTreeMap::new();
790            for (k, v) in m {
791                result.insert(k, extend_value(v, op, base).await?);
792            }
793            Ok(Value::Map(result))
794        }
795        _ => Ok(value),
796    }
797}
798
799impl FromStr for Value {
800    type Err = std::convert::Infallible;
801    fn from_str(s: &str) -> Result<Self, Self::Err> {
802        Ok(if let Ok(v) = s.parse::<u64>() {
803            Value::U64(v)
804        } else if let Ok(v) = s.parse::<i64>() {
805            Value::I64(v)
806        } else if let Ok(v) = s.parse::<f64>() {
807            Value::F64(v)
808        } else {
809            serde_json::from_str(s).unwrap_or_else(|_| {
810                let s_l = s.to_lowercase();
811                match s_l.as_str() {
812                    "true" => Value::Bool(true),
813                    "false" => Value::Bool(false),
814                    "none" | "null" => Value::Unit,
815                    _ => Value::String(s.to_owned()),
816                }
817            })
818        })
819    }
820}
821
822#[cfg(feature = "extended-value")]
823async fn extend_string_value(val: String, op: &crate::op::Op, base: &Path) -> EResult<Value> {
824    if let Some(s) = val.strip_prefix('^') {
825        let mut sp = s.splitn(2, ' ');
826        let cmd = sp.next().unwrap();
827        macro_rules! pipe {
828            () => {{
829                let cmd = sp
830                    .next()
831                    .ok_or_else(|| Error::invalid_params("xvalue pipe: command not specified"))?;
832                let cd_cmd = format!("cd \"{}\" && {}", base.to_string_lossy(), cmd);
833                let res = bmart::process::command(
834                    "sh",
835                    &["-c", &cd_cmd],
836                    op.timeout()?,
837                    bmart::process::Options::default(),
838                )
839                .await?;
840                if res.ok() {
841                    res.out.join("\n")
842                } else {
843                    return Err(Error::failed(format!(
844                        "xvalue pipe command failed to execute: {}",
845                        res.err.join("\n")
846                    )));
847                }
848            }};
849        }
850        match cmd {
851            "include" => {
852                let fname = sp.next().ok_or_else(|| {
853                    Error::invalid_params("xvalue include: file name not specified")
854                })?;
855                let mut path = base.to_path_buf();
856                path.push(fname);
857                let content = tokio::time::timeout(op.timeout()?, tokio::fs::read(path)).await??;
858                let val: Value = serde_yaml::from_slice(&content).map_err(Error::invalid_data)?;
859                Ok(val)
860            }
861            "include-text" => {
862                let fname = sp.next().ok_or_else(|| {
863                    Error::invalid_params("xvalue include: file name not specified")
864                })?;
865                let mut path = base.to_path_buf();
866                path.push(fname);
867                let content =
868                    tokio::time::timeout(op.timeout()?, tokio::fs::read_to_string(path)).await??;
869                Ok(Value::String(content.trim_end().to_string()))
870            }
871            "pipe" => {
872                let s = pipe!();
873                let val: Value = serde_yaml::from_str(&s).map_err(Error::invalid_data)?;
874                Ok(val)
875            }
876            "pipe-text" => {
877                let s = pipe!();
878                Ok(Value::String(s.trim_end().to_string()))
879            }
880            _ => Ok(Value::String(if s.starts_with('^') {
881                s.to_owned()
882            } else {
883                val
884            })),
885        }
886    } else {
887        Ok(Value::String(val))
888    }
889}
890
891impl Eq for Value {}
892impl PartialOrd for Value {
893    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
894        Some(self.cmp(rhs))
895    }
896}
897
898macro_rules! impl_from {
899    ($v: ty, $val: expr) => {
900        impl From<$v> for Value {
901            fn from(src: $v) -> Value {
902                $val(src)
903            }
904        }
905    };
906}
907
908impl_from!(bool, Value::Bool);
909impl_from!(u8, Value::U8);
910impl_from!(i8, Value::I8);
911impl_from!(u16, Value::U16);
912impl_from!(i16, Value::I16);
913impl_from!(u32, Value::U32);
914impl_from!(i32, Value::I32);
915impl_from!(u64, Value::U64);
916impl_from!(i64, Value::I64);
917impl_from!(f32, Value::F32);
918impl_from!(f64, Value::F64);
919impl_from!(String, Value::String);
920
921// comparing $from unsigned bigger
922macro_rules! ngt {
923    ($n: expr, $from: ident, $to: ident) => {
924        if $n > $to::MAX as $from {
925            return Err(Error::invalid_data_static(ERR_TOO_BIG_NUMBER));
926        } else {
927            $n as $to
928        }
929    };
930}
931// comparing $from signed bigger $to signed/unsigned smaller
932macro_rules! ngt_nlt {
933    ($n: expr, $from: ident, $to: ident) => {
934        if $n > $to::MAX as $from {
935            return Err(Error::invalid_data_static(ERR_TOO_BIG_NUMBER));
936        } else if $n < $to::MIN as $from {
937            return Err(Error::invalid_data_static(ERR_TOO_SMALL_NUMBER));
938        } else {
939            $n as $to
940        }
941    };
942}
943// comparing $from smaller signed with $to unsigned (check that $from is zero-positive)
944macro_rules! nltz {
945    ($n: expr, $from: ident, $to: ident) => {
946        if $n < 0 as $from {
947            return Err(Error::invalid_data_static(ERR_TOO_SMALL_NUMBER));
948        } else {
949            $n as $to
950        }
951    };
952}
953
954impl TryFrom<Value> for u8 {
955    type Error = Error;
956
957    fn try_from(value: Value) -> EResult<u8> {
958        match value {
959            Value::Bool(v) => Ok(u8::from(v)),
960            Value::U8(v) => Ok(v),
961            Value::U16(v) => Ok(ngt!(v, u16, u8)),
962            Value::U32(v) => Ok(ngt!(v, u32, u8)),
963            Value::U64(v) => Ok(ngt!(v, u64, u8)),
964            Value::I8(v) => Ok(nltz!(v, i8, u8)),
965            Value::I16(v) => Ok(ngt_nlt!(v, i16, u8)),
966            Value::I32(v) => Ok(ngt_nlt!(v, i32, u8)),
967            Value::I64(v) => Ok(ngt_nlt!(v, i64, u8)),
968            Value::F32(v) => Ok(ngt_nlt!(v, f32, u8)),
969            Value::F64(v) => Ok(ngt_nlt!(v, f64, u8)),
970            Value::String(v) => Ok(v.parse::<u8>()?),
971            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
972        }
973    }
974}
975
976impl TryFrom<&Value> for u8 {
977    type Error = Error;
978
979    fn try_from(value: &Value) -> EResult<u8> {
980        match value {
981            Value::Bool(v) => Ok(u8::from(*v)),
982            Value::U8(v) => Ok(*v),
983            Value::U16(v) => Ok(ngt!(*v, u16, u8)),
984            Value::U32(v) => Ok(ngt!(*v, u32, u8)),
985            Value::U64(v) => Ok(ngt!(*v, u64, u8)),
986            Value::I8(v) => Ok(nltz!(*v, i8, u8)),
987            Value::I16(v) => Ok(ngt_nlt!(*v, i16, u8)),
988            Value::I32(v) => Ok(ngt_nlt!(*v, i32, u8)),
989            Value::I64(v) => Ok(ngt_nlt!(*v, i64, u8)),
990            Value::F32(v) => Ok(ngt_nlt!(*v, f32, u8)),
991            Value::F64(v) => Ok(ngt_nlt!(*v, f64, u8)),
992            Value::String(v) => Ok(v.parse::<u8>()?),
993            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
994        }
995    }
996}
997
998impl TryFrom<Value> for i8 {
999    type Error = Error;
1000
1001    fn try_from(value: Value) -> EResult<i8> {
1002        match value {
1003            Value::Bool(v) => Ok(i8::from(v)),
1004            Value::U8(v) => Ok(ngt!(v, u8, i8)),
1005            Value::U16(v) => Ok(ngt!(v, u16, i8)),
1006            Value::U32(v) => Ok(ngt!(v, u32, i8)),
1007            Value::U64(v) => Ok(ngt!(v, u64, i8)),
1008            Value::I8(v) => Ok(v),
1009            Value::I16(v) => Ok(ngt_nlt!(v, i16, i8)),
1010            Value::I32(v) => Ok(ngt_nlt!(v, i32, i8)),
1011            Value::I64(v) => Ok(ngt_nlt!(v, i64, i8)),
1012            Value::F32(v) => Ok(ngt_nlt!(v, f32, i8)),
1013            Value::F64(v) => Ok(ngt_nlt!(v, f64, i8)),
1014            Value::String(v) => Ok(v.parse::<i8>()?),
1015            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1016        }
1017    }
1018}
1019
1020impl TryFrom<&Value> for i8 {
1021    type Error = Error;
1022
1023    fn try_from(value: &Value) -> EResult<i8> {
1024        match value {
1025            Value::Bool(v) => Ok(i8::from(*v)),
1026            Value::U8(v) => Ok(ngt!(*v, u8, i8)),
1027            Value::U16(v) => Ok(ngt!(*v, u16, i8)),
1028            Value::U32(v) => Ok(ngt!(*v, u32, i8)),
1029            Value::U64(v) => Ok(ngt!(*v, u64, i8)),
1030            Value::I8(v) => Ok(*v),
1031            Value::I16(v) => Ok(ngt_nlt!(*v, i16, i8)),
1032            Value::I32(v) => Ok(ngt_nlt!(*v, i32, i8)),
1033            Value::I64(v) => Ok(ngt_nlt!(*v, i64, i8)),
1034            Value::F32(v) => Ok(ngt_nlt!(*v, f32, i8)),
1035            Value::F64(v) => Ok(ngt_nlt!(*v, f64, i8)),
1036            Value::String(v) => Ok(v.parse::<i8>()?),
1037            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1038        }
1039    }
1040}
1041
1042impl TryFrom<Value> for u16 {
1043    type Error = Error;
1044
1045    fn try_from(value: Value) -> EResult<u16> {
1046        match value {
1047            Value::Bool(v) => Ok(u16::from(v)),
1048            Value::U8(v) => Ok(u16::from(v)),
1049            Value::U16(v) => Ok(v),
1050            Value::U32(v) => Ok(ngt!(v, u32, u16)),
1051            Value::U64(v) => Ok(ngt!(v, u64, u16)),
1052            Value::I8(v) => Ok(nltz!(v, i8, u16)),
1053            Value::I16(v) => Ok(nltz!(v, i16, u16)),
1054            Value::I32(v) => Ok(ngt_nlt!(v, i32, u16)),
1055            Value::I64(v) => Ok(ngt_nlt!(v, i64, u16)),
1056            Value::F32(v) => Ok(ngt_nlt!(v, f32, u16)),
1057            Value::F64(v) => Ok(ngt_nlt!(v, f64, u16)),
1058            Value::String(v) => Ok(v.parse::<u16>()?),
1059            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1060        }
1061    }
1062}
1063
1064impl TryFrom<&Value> for u16 {
1065    type Error = Error;
1066
1067    fn try_from(value: &Value) -> EResult<u16> {
1068        match value {
1069            Value::Bool(v) => Ok(u16::from(*v)),
1070            Value::U8(v) => Ok(u16::from(*v)),
1071            Value::U16(v) => Ok(*v),
1072            Value::U32(v) => Ok(ngt!(*v, u32, u16)),
1073            Value::U64(v) => Ok(ngt!(*v, u64, u16)),
1074            Value::I8(v) => Ok(nltz!(*v, i8, u16)),
1075            Value::I16(v) => Ok(nltz!(*v, i16, u16)),
1076            Value::I32(v) => Ok(ngt_nlt!(*v, i32, u16)),
1077            Value::I64(v) => Ok(ngt_nlt!(*v, i64, u16)),
1078            Value::F32(v) => Ok(ngt_nlt!(*v, f32, u16)),
1079            Value::F64(v) => Ok(ngt_nlt!(*v, f64, u16)),
1080            Value::String(v) => Ok(v.parse::<u16>()?),
1081            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1082        }
1083    }
1084}
1085
1086impl TryFrom<Value> for i16 {
1087    type Error = Error;
1088
1089    fn try_from(value: Value) -> EResult<i16> {
1090        match value {
1091            Value::Bool(v) => Ok(i16::from(v)),
1092            Value::U8(v) => Ok(i16::from(v)),
1093            Value::U16(v) => Ok(ngt!(v, u16, i16)),
1094            Value::U32(v) => Ok(ngt!(v, u32, i16)),
1095            Value::U64(v) => Ok(ngt!(v, u64, i16)),
1096            Value::I8(v) => Ok(i16::from(v)),
1097            Value::I16(v) => Ok(v),
1098            Value::I32(v) => Ok(ngt_nlt!(v, i32, i16)),
1099            Value::I64(v) => Ok(ngt_nlt!(v, i64, i16)),
1100            Value::F32(v) => Ok(ngt_nlt!(v, f32, i16)),
1101            Value::F64(v) => Ok(ngt_nlt!(v, f64, i16)),
1102            Value::String(v) => Ok(v.parse::<i16>()?),
1103            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1104        }
1105    }
1106}
1107
1108impl TryFrom<&Value> for i16 {
1109    type Error = Error;
1110
1111    fn try_from(value: &Value) -> EResult<i16> {
1112        match value {
1113            Value::Bool(v) => Ok(i16::from(*v)),
1114            Value::U8(v) => Ok(i16::from(*v)),
1115            Value::U16(v) => Ok(ngt!(*v, u16, i16)),
1116            Value::U32(v) => Ok(ngt!(*v, u32, i16)),
1117            Value::U64(v) => Ok(ngt!(*v, u64, i16)),
1118            Value::I8(v) => Ok(i16::from(*v)),
1119            Value::I16(v) => Ok(*v),
1120            Value::I32(v) => Ok(ngt_nlt!(*v, i32, i16)),
1121            Value::I64(v) => Ok(ngt_nlt!(*v, i64, i16)),
1122            Value::F32(v) => Ok(ngt_nlt!(*v, f32, i16)),
1123            Value::F64(v) => Ok(ngt_nlt!(*v, f64, i16)),
1124            Value::String(v) => Ok(v.parse::<i16>()?),
1125            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1126        }
1127    }
1128}
1129
1130impl TryFrom<Value> for u32 {
1131    type Error = Error;
1132
1133    fn try_from(value: Value) -> EResult<u32> {
1134        match value {
1135            Value::Bool(v) => Ok(u32::from(v)),
1136            Value::U8(v) => Ok(u32::from(v)),
1137            Value::U16(v) => Ok(u32::from(v)),
1138            Value::U32(v) => Ok(v),
1139            Value::U64(v) => Ok(ngt!(v, u64, u32)),
1140            Value::I8(v) => Ok(nltz!(v, i8, u32)),
1141            Value::I16(v) => Ok(nltz!(v, i16, u32)),
1142            Value::I32(v) => Ok(nltz!(v, i32, u32)),
1143            Value::I64(v) => Ok(ngt_nlt!(v, i64, u32)),
1144            Value::F32(v) => Ok(nltz!(v, f32, u32)),
1145            Value::F64(v) => Ok(ngt_nlt!(v, f64, u32)),
1146            Value::String(v) => Ok(v.parse::<u32>()?),
1147            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1148        }
1149    }
1150}
1151
1152impl TryFrom<&Value> for u32 {
1153    type Error = Error;
1154
1155    fn try_from(value: &Value) -> EResult<u32> {
1156        match value {
1157            Value::Bool(v) => Ok(u32::from(*v)),
1158            Value::U8(v) => Ok(u32::from(*v)),
1159            Value::U16(v) => Ok(u32::from(*v)),
1160            Value::U32(v) => Ok(*v),
1161            Value::U64(v) => Ok(ngt!(*v, u64, u32)),
1162            Value::I8(v) => Ok(nltz!(*v, i8, u32)),
1163            Value::I16(v) => Ok(nltz!(*v, i16, u32)),
1164            Value::I32(v) => Ok(nltz!(*v, i32, u32)),
1165            Value::I64(v) => Ok(ngt_nlt!(*v, i64, u32)),
1166            Value::F32(v) => Ok(nltz!(*v, f32, u32)),
1167            Value::F64(v) => Ok(ngt_nlt!(*v, f64, u32)),
1168            Value::String(v) => Ok(v.parse::<u32>()?),
1169            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1170        }
1171    }
1172}
1173
1174impl TryFrom<Value> for i32 {
1175    type Error = Error;
1176
1177    fn try_from(value: Value) -> EResult<i32> {
1178        match value {
1179            Value::Bool(v) => Ok(i32::from(v)),
1180            Value::U8(v) => Ok(i32::from(v)),
1181            Value::U16(v) => Ok(i32::from(v)),
1182            Value::U32(v) => Ok(ngt!(v, u32, i32)),
1183            Value::U64(v) => Ok(ngt!(v, u64, i32)),
1184            Value::I8(v) => Ok(i32::from(v)),
1185            Value::I16(v) => Ok(i32::from(v)),
1186            Value::I32(v) => Ok(v),
1187            Value::I64(v) => Ok(ngt_nlt!(v, i64, i32)),
1188            #[allow(clippy::cast_possible_truncation)]
1189            Value::F32(v) => Ok(v as i32),
1190            Value::F64(v) => Ok(ngt_nlt!(v, f64, i32)),
1191            Value::String(v) => Ok(v.parse::<i32>()?),
1192            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1193        }
1194    }
1195}
1196
1197impl TryFrom<&Value> for i32 {
1198    type Error = Error;
1199
1200    fn try_from(value: &Value) -> EResult<i32> {
1201        match value {
1202            Value::Bool(v) => Ok(i32::from(*v)),
1203            Value::U8(v) => Ok(i32::from(*v)),
1204            Value::U16(v) => Ok(i32::from(*v)),
1205            Value::U32(v) => Ok(ngt!(*v, u32, i32)),
1206            Value::U64(v) => Ok(ngt!(*v, u64, i32)),
1207            Value::I8(v) => Ok(i32::from(*v)),
1208            Value::I16(v) => Ok(i32::from(*v)),
1209            Value::I32(v) => Ok(*v),
1210            Value::I64(v) => Ok(ngt_nlt!(*v, i64, i32)),
1211            #[allow(clippy::cast_possible_truncation)]
1212            Value::F32(v) => Ok(*v as i32),
1213            Value::F64(v) => Ok(ngt_nlt!(*v, f64, i32)),
1214            Value::String(v) => Ok(v.parse::<i32>()?),
1215            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1216        }
1217    }
1218}
1219
1220impl TryFrom<&Value> for u64 {
1221    type Error = Error;
1222
1223    fn try_from(value: &Value) -> EResult<u64> {
1224        match value {
1225            Value::Bool(v) => Ok(u64::from(*v)),
1226            Value::U8(v) => Ok(u64::from(*v)),
1227            Value::U16(v) => Ok(u64::from(*v)),
1228            Value::U32(v) => Ok(u64::from(*v)),
1229            Value::U64(v) => Ok(*v),
1230            Value::I8(v) => Ok(nltz!(*v, i8, u64)),
1231            Value::I16(v) => Ok(nltz!(*v, i16, u64)),
1232            Value::I32(v) => Ok(nltz!(*v, i32, u64)),
1233            Value::I64(v) => Ok(nltz!(*v, i64, u64)),
1234            Value::F32(v) => Ok(nltz!(*v, f32, u64)),
1235            Value::F64(v) => Ok(nltz!(*v, f64, u64)),
1236            Value::String(v) => Ok(v.parse::<u64>()?),
1237            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1238        }
1239    }
1240}
1241
1242impl TryFrom<Value> for u64 {
1243    type Error = Error;
1244
1245    fn try_from(value: Value) -> EResult<u64> {
1246        match value {
1247            Value::Bool(v) => Ok(u64::from(v)),
1248            Value::U8(v) => Ok(u64::from(v)),
1249            Value::U16(v) => Ok(u64::from(v)),
1250            Value::U32(v) => Ok(u64::from(v)),
1251            Value::U64(v) => Ok(v),
1252            Value::I8(v) => Ok(nltz!(v, i8, u64)),
1253            Value::I16(v) => Ok(nltz!(v, i16, u64)),
1254            Value::I32(v) => Ok(nltz!(v, i32, u64)),
1255            Value::I64(v) => Ok(nltz!(v, i64, u64)),
1256            Value::F32(v) => Ok(nltz!(v, f32, u64)),
1257            Value::F64(v) => Ok(nltz!(v, f64, u64)),
1258            Value::String(v) => Ok(v.parse::<u64>()?),
1259            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1260        }
1261    }
1262}
1263
1264impl TryFrom<&Value> for i64 {
1265    type Error = Error;
1266
1267    fn try_from(value: &Value) -> EResult<i64> {
1268        match value {
1269            Value::Bool(v) => Ok(i64::from(*v)),
1270            Value::U8(v) => Ok(i64::from(*v)),
1271            Value::U16(v) => Ok(i64::from(*v)),
1272            Value::U32(v) => Ok(i64::from(*v)),
1273            Value::U64(v) => Ok(ngt!(*v, u64, i64)),
1274            Value::I8(v) => Ok(i64::from(*v)),
1275            Value::I16(v) => Ok(i64::from(*v)),
1276            Value::I32(v) => Ok(i64::from(*v)),
1277            Value::I64(v) => Ok(*v),
1278            #[allow(clippy::cast_possible_truncation)]
1279            Value::F32(v) => Ok(*v as i64),
1280            #[allow(clippy::cast_possible_truncation)]
1281            Value::F64(v) => Ok(*v as i64),
1282            Value::String(v) => Ok(v.parse::<i64>()?),
1283            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1284        }
1285    }
1286}
1287
1288impl TryFrom<Value> for i64 {
1289    type Error = Error;
1290
1291    fn try_from(value: Value) -> EResult<i64> {
1292        match value {
1293            Value::Bool(v) => Ok(i64::from(v)),
1294            Value::U8(v) => Ok(i64::from(v)),
1295            Value::U16(v) => Ok(i64::from(v)),
1296            Value::U32(v) => Ok(i64::from(v)),
1297            Value::U64(v) => Ok(ngt!(v, u64, i64)),
1298            Value::I8(v) => Ok(i64::from(v)),
1299            Value::I16(v) => Ok(i64::from(v)),
1300            Value::I32(v) => Ok(i64::from(v)),
1301            Value::I64(v) => Ok(v),
1302            #[allow(clippy::cast_possible_truncation)]
1303            Value::F32(v) => Ok(v as i64),
1304            #[allow(clippy::cast_possible_truncation)]
1305            Value::F64(v) => Ok(v as i64),
1306            Value::String(v) => Ok(v.parse::<i64>()?),
1307            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1308        }
1309    }
1310}
1311
1312impl TryFrom<Value> for f32 {
1313    type Error = Error;
1314
1315    fn try_from(value: Value) -> EResult<f32> {
1316        match value {
1317            Value::Bool(v) => Ok(float_from_bool!(v)),
1318            Value::F32(v) => Ok(v),
1319            Value::F64(v) => Ok(ngt_nlt!(v, f64, f32)),
1320            Value::U8(v) => Ok(f32::from(v)),
1321            Value::U16(v) => Ok(f32::from(v)),
1322            Value::U32(v) => Ok(ngt!(v, u32, f32)),
1323            Value::U64(v) => Ok(ngt!(v, u64, f32)),
1324            Value::I8(v) => Ok(f32::from(v)),
1325            Value::I16(v) => Ok(f32::from(v)),
1326            Value::I32(v) => Ok(ngt_nlt!(v, i32, f32)),
1327            Value::I64(v) => Ok(ngt_nlt!(v, i64, f32)),
1328            Value::String(v) => Ok(v.parse::<f32>()?),
1329            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1330        }
1331    }
1332}
1333
1334impl TryFrom<&Value> for f32 {
1335    type Error = Error;
1336
1337    fn try_from(value: &Value) -> EResult<f32> {
1338        match value {
1339            Value::Bool(v) => Ok(float_from_bool!(*v)),
1340            Value::F32(v) => Ok(*v),
1341            Value::F64(v) => Ok(ngt_nlt!(*v, f64, f32)),
1342            Value::U8(v) => Ok(f32::from(*v)),
1343            Value::U16(v) => Ok(f32::from(*v)),
1344            Value::U32(v) => Ok(ngt!(*v, u32, f32)),
1345            Value::U64(v) => Ok(ngt!(*v, u64, f32)),
1346            Value::I8(v) => Ok(f32::from(*v)),
1347            Value::I16(v) => Ok(f32::from(*v)),
1348            Value::I32(v) => Ok(ngt_nlt!(*v, i32, f32)),
1349            Value::I64(v) => Ok(ngt_nlt!(*v, i64, f32)),
1350            Value::String(v) => Ok(v.parse::<f32>()?),
1351            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1352        }
1353    }
1354}
1355
1356impl TryFrom<&Value> for f64 {
1357    type Error = Error;
1358
1359    fn try_from(value: &Value) -> EResult<f64> {
1360        match value {
1361            Value::Bool(v) => Ok(float_from_bool!(*v)),
1362            Value::U8(v) => Ok(f64::from(*v)),
1363            Value::U16(v) => Ok(f64::from(*v)),
1364            Value::U32(v) => Ok(f64::from(*v)),
1365            Value::U64(v) => Ok(ngt!(*v, u64, f64)),
1366            Value::I8(v) => Ok(f64::from(*v)),
1367            Value::I16(v) => Ok(f64::from(*v)),
1368            Value::I32(v) => Ok(f64::from(*v)),
1369            Value::I64(v) => Ok(ngt_nlt!(*v, i64, f64)),
1370            Value::F32(v) => Ok(f64::from(*v)),
1371            Value::F64(v) => Ok(*v),
1372            Value::String(v) => Ok(v.parse::<f64>()?),
1373            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1374        }
1375    }
1376}
1377
1378impl TryFrom<Value> for f64 {
1379    type Error = Error;
1380
1381    fn try_from(value: Value) -> EResult<f64> {
1382        match value {
1383            Value::Bool(v) => Ok(float_from_bool!(v)),
1384            Value::U8(v) => Ok(f64::from(v)),
1385            Value::U16(v) => Ok(f64::from(v)),
1386            Value::U32(v) => Ok(f64::from(v)),
1387            Value::U64(v) => Ok(ngt!(v, u64, f64)),
1388            Value::I8(v) => Ok(f64::from(v)),
1389            Value::I16(v) => Ok(f64::from(v)),
1390            Value::I32(v) => Ok(f64::from(v)),
1391            Value::I64(v) => Ok(ngt_nlt!(v, i64, f64)),
1392            Value::F32(v) => Ok(f64::from(v)),
1393            Value::F64(v) => Ok(v),
1394            Value::String(v) => Ok(v.parse::<f64>()?),
1395            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1396        }
1397    }
1398}
1399
1400impl TryFrom<Value> for Option<std::time::Duration> {
1401    type Error = Error;
1402
1403    fn try_from(v: Value) -> EResult<Option<std::time::Duration>> {
1404        let t: f64 = v.try_into()?;
1405        if t > 0.0 {
1406            Ok(Some(std::time::Duration::from_secs_f64(t)))
1407        } else {
1408            Ok(None)
1409        }
1410    }
1411}
1412
1413impl TryFrom<Value> for String {
1414    type Error = Error;
1415
1416    fn try_from(v: Value) -> EResult<String> {
1417        match v {
1418            Value::Option(Some(s)) => Ok((*s).try_into()?),
1419            Value::String(s) => Ok(s),
1420            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1421        }
1422    }
1423}
1424
1425impl TryFrom<&Value> for String {
1426    type Error = Error;
1427
1428    fn try_from(v: &Value) -> EResult<String> {
1429        match v {
1430            Value::Option(Some(s)) => Ok(s.as_ref().try_into()?),
1431            Value::String(s) => Ok(s.clone()),
1432            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1433        }
1434    }
1435}
1436
1437impl<'a> TryFrom<&'a Value> for &'a str {
1438    type Error = Error;
1439
1440    fn try_from(v: &'a Value) -> EResult<&'a str> {
1441        match v {
1442            Value::Option(Some(s)) => Ok(s.as_ref().try_into()?),
1443            Value::String(s) => Ok(s),
1444            _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1445        }
1446    }
1447}
1448
1449impl TryFrom<Value> for Option<String> {
1450    type Error = Error;
1451
1452    fn try_from(v: Value) -> EResult<Option<String>> {
1453        let s = match v {
1454            Value::Option(v) => match v {
1455                Some(s) => (*s).try_into()?,
1456                None => return Ok(None),
1457            },
1458            Value::Unit => return Ok(None),
1459            Value::String(s) => s,
1460            _ => {
1461                return Err(Error::invalid_data_static(ERR_INVALID_VALUE));
1462            }
1463        };
1464        Ok(if s.is_empty() { None } else { Some(s) })
1465    }
1466}
1467
1468impl TryFrom<Value> for std::time::Duration {
1469    type Error = Error;
1470
1471    fn try_from(v: Value) -> EResult<std::time::Duration> {
1472        Ok(std::time::Duration::from_secs_f64(v.try_into()?))
1473    }
1474}
1475
1476impl TryFrom<Value> for Vec<Value> {
1477    type Error = Error;
1478
1479    fn try_from(value: Value) -> EResult<Vec<Value>> {
1480        match value {
1481            Value::Seq(vec) => Ok(vec),
1482            Value::String(s) => Ok(s.split(',').map(|s| Value::String(s.to_owned())).collect()),
1483            _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1484        }
1485    }
1486}
1487
1488impl<S: BuildHasher + Default> TryFrom<Value> for HashSet<Value, S> {
1489    type Error = Error;
1490
1491    fn try_from(value: Value) -> EResult<HashSet<Value, S>> {
1492        match value {
1493            Value::Seq(vec) => Ok(HashSet::from_iter(vec)),
1494            Value::String(s) => Ok(s.split(',').map(|s| Value::String(s.to_owned())).collect()),
1495            _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1496        }
1497    }
1498}
1499
1500impl From<HashSet<ipnetwork::IpNetwork>> for Value {
1501    fn from(v: HashSet<ipnetwork::IpNetwork>) -> Value {
1502        to_value(v).unwrap()
1503    }
1504}
1505
1506impl<S: BuildHasher + Default> TryFrom<Value> for HashSet<ipnetwork::IpNetwork, S> {
1507    type Error = Error;
1508
1509    fn try_from(value: Value) -> EResult<HashSet<ipnetwork::IpNetwork, S>> {
1510        match value {
1511            Value::Seq(vec) => {
1512                let mut result = HashSet::default();
1513                for v in vec {
1514                    result.insert(v.deserialize_into()?);
1515                }
1516                Ok(result)
1517            }
1518            Value::String(s) => {
1519                let mut result = HashSet::default();
1520                for v in s.split(',') {
1521                    result.insert(v.parse()?);
1522                }
1523                Ok(result)
1524            }
1525            _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1526        }
1527    }
1528}
1529
1530impl TryFrom<Value> for Vec<String> {
1531    type Error = Error;
1532
1533    fn try_from(value: Value) -> EResult<Vec<String>> {
1534        match value {
1535            Value::Seq(vec) => {
1536                let mut result = Vec::new();
1537                for v in vec {
1538                    result.push(v.try_into()?);
1539                }
1540                Ok(result)
1541            }
1542            Value::String(s) => Ok(s.split(',').map(ToOwned::to_owned).collect()),
1543            _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1544        }
1545    }
1546}
1547
1548impl TryFrom<&Value> for Vec<String> {
1549    type Error = Error;
1550
1551    fn try_from(value: &Value) -> EResult<Vec<String>> {
1552        match value {
1553            Value::Seq(vec) => {
1554                let mut result = Vec::new();
1555                for v in vec {
1556                    result.push(v.try_into()?);
1557                }
1558                Ok(result)
1559            }
1560            Value::String(s) => Ok(s.split(',').map(ToOwned::to_owned).collect()),
1561            _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1562        }
1563    }
1564}
1565
1566impl<'a> TryFrom<&'a Value> for Vec<&'a str> {
1567    type Error = Error;
1568
1569    fn try_from(value: &'a Value) -> EResult<Vec<&'a str>> {
1570        match value {
1571            Value::Seq(vec) => {
1572                let mut result = Vec::new();
1573                for v in vec {
1574                    result.push(v.try_into()?);
1575                }
1576                Ok(result)
1577            }
1578            Value::String(s) => Ok(s.split(',').collect()),
1579            _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1580        }
1581    }
1582}
1583
1584impl TryFrom<Value> for bool {
1585    type Error = Error;
1586
1587    fn try_from(value: Value) -> EResult<bool> {
1588        match value {
1589            Value::Bool(v) => Ok(v),
1590            Value::String(s) => match s.to_lowercase().as_str() {
1591                "true" | "1" | "yes" => Ok(true),
1592                "false" | "0" | "no" => Ok(false),
1593                _ => Err(Error::invalid_data_static(ERR_INVALID_BOOLEAN_VALUE)),
1594            },
1595            _ => {
1596                let n: u64 = value
1597                    .try_into()
1598                    .map_err(|_| Error::invalid_data_static(ERR_INVALID_BOOLEAN_VALUE))?;
1599                if n == 0 {
1600                    Ok(false)
1601                } else if n == 1 {
1602                    Ok(true)
1603                } else {
1604                    Err(Error::invalid_data_static(ERR_INVALID_BOOLEAN_VALUE))
1605                }
1606            }
1607        }
1608    }
1609}
1610
1611impl From<&str> for Value {
1612    fn from(s: &str) -> Value {
1613        Value::String(s.to_owned())
1614    }
1615}
1616
1617impl From<&String> for Value {
1618    fn from(s: &String) -> Value {
1619        Value::String(s.clone())
1620    }
1621}
1622
1623impl From<Vec<Value>> for Value {
1624    fn from(v: Vec<Value>) -> Value {
1625        Value::Seq(v)
1626    }
1627}
1628
1629impl From<HashSet<Value>> for Value {
1630    fn from(v: HashSet<Value>) -> Value {
1631        Value::Seq(Vec::from_iter(v))
1632    }
1633}
1634
1635impl From<Vec<String>> for Value {
1636    fn from(v: Vec<String>) -> Value {
1637        Value::Seq(v.iter().map(Into::into).collect::<Vec<Value>>())
1638    }
1639}
1640
1641impl From<BTreeMap<Value, Value>> for Value {
1642    fn from(v: BTreeMap<Value, Value>) -> Value {
1643        Value::Map(v)
1644    }
1645}
1646
1647impl From<std::time::Duration> for Value {
1648    fn from(v: std::time::Duration) -> Value {
1649        v.as_secs_f64().into()
1650    }
1651}
1652
1653impl From<Option<std::time::Duration>> for Value {
1654    fn from(v: Option<std::time::Duration>) -> Value {
1655        v.map_or(Value::Unit, |d| d.as_secs_f64().into())
1656    }
1657}
1658
1659impl From<Option<f64>> for Value {
1660    fn from(v: Option<f64>) -> Value {
1661        v.map_or(Value::Unit, Value::F64)
1662    }
1663}
1664
1665impl From<Option<String>> for Value {
1666    fn from(v: Option<String>) -> Value {
1667        v.map_or(Value::Unit, Into::into)
1668    }
1669}
1670
1671impl TryFrom<Value> for serde_json::Value {
1672    type Error = Error;
1673    fn try_from(v: Value) -> EResult<Self> {
1674        serde_json::to_value(v).map_err(Into::into)
1675    }
1676}
1677
1678impl TryFrom<serde_json::Value> for Value {
1679    type Error = Error;
1680    fn try_from(v: serde_json::Value) -> EResult<Self> {
1681        serde_json::from_value(v).map_err(Into::into)
1682    }
1683}
1684
1685#[cfg(test)]
1686mod test {
1687    use crate::prelude::*;
1688    use serde::Serialize;
1689
1690    #[test]
1691    fn test_val_pack() -> EResult<()> {
1692        #[derive(Serialize)]
1693        struct My {
1694            test: bool,
1695            abc: usize,
1696        }
1697
1698        let my = My {
1699            test: true,
1700            abc: 123,
1701        };
1702        let mut valx: Value = to_value(my)?;
1703        valx = valx.unpack()?;
1704        let vlstr = valx.clone().to_string_or_pack()?;
1705        dbg!(&vlstr);
1706        let mut val = Value::String(vlstr);
1707        val = val.unpack()?;
1708        assert_eq!(val, valx);
1709        Ok(())
1710    }
1711
1712    #[test]
1713    fn test_val_parse() {
1714        let val: Value = "12345.111".parse().unwrap();
1715        assert_eq!(val, Value::F64(12345.111));
1716        let val: Value = "12345".parse().unwrap();
1717        assert_eq!(val, Value::U64(12345));
1718        let val: Value = "-12345".parse().unwrap();
1719        assert_eq!(val, Value::I64(-12345));
1720        let val: Value = "True".parse().unwrap();
1721        assert_eq!(val, Value::Bool(true));
1722        let val: Value = "False".parse().unwrap();
1723        assert_eq!(val, Value::Bool(false));
1724        let val: Value = "None".parse().unwrap();
1725        assert_eq!(val, Value::Unit);
1726        let val: Value = "Null".parse().unwrap();
1727        assert_eq!(val, Value::Unit);
1728    }
1729}