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