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 {
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 #[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::I64(vf.round() as i64));
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::I32(vf.round() as i32));
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 pub fn as_timestamp(&self) -> EResult<f64> {
582 self.as_ts(true)
583 }
584
585 #[cfg(feature = "time")]
586 #[inline]
587 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 is_true(&self) -> bool {
613 match self {
614 Value::Bool(v) => *v,
615 Value::U8(v) => *v != 0,
616 Value::U16(v) => *v != 0,
617 Value::U32(v) => *v != 0,
618 Value::U64(v) => *v != 0,
619 Value::I8(v) => *v != 0,
620 Value::I16(v) => *v != 0,
621 Value::I32(v) => *v != 0,
622 Value::I64(v) => *v != 0,
623 Value::F32(v) => *v != 0.0,
624 Value::F64(v) => *v != 0.0,
625 Value::String(v) => {
626 let v_l = v.to_lowercase();
627 v_l == "true" || v_l == "yes" || v_l == "1"
628 }
629 _ => false,
630 }
631 }
632
633 pub fn to_alphanumeric_string(self) -> EResult<String> {
634 match self {
635 Value::Bool(v) => Ok(v.to_string()),
636 Value::U8(v) => Ok(v.to_string()),
637 Value::U16(v) => Ok(v.to_string()),
638 Value::U32(v) => Ok(v.to_string()),
639 Value::U64(v) => Ok(v.to_string()),
640 Value::I8(v) => Ok(v.to_string()),
641 Value::I16(v) => Ok(v.to_string()),
642 Value::I32(v) => Ok(v.to_string()),
643 Value::I64(v) => Ok(v.to_string()),
644 Value::F32(v) => Ok(v.to_string()),
645 Value::F64(v) => Ok(v.to_string()),
646 Value::Char(v) => Ok(v.to_string()),
647 Value::String(v) => {
648 for c in v.chars() {
649 if !c.is_alphanumeric() {
650 return Err(Error::invalid_params(format!("invalid symbols in {}", v)));
651 }
652 }
653 Ok(v)
654 }
655 Value::Unit => Ok("null".to_owned()),
656 _ => Err(Error::invalid_data(format!(
657 "unable to get string from {:?}",
658 self
659 ))),
660 }
661 }
662
663 pub fn to_string_or_pack(self) -> EResult<String> {
664 match self {
665 Value::U8(v) => Ok(v.to_string()),
666 Value::U16(v) => Ok(v.to_string()),
667 Value::U32(v) => Ok(v.to_string()),
668 Value::U64(v) => Ok(v.to_string()),
669 Value::I8(v) => Ok(v.to_string()),
670 Value::I16(v) => Ok(v.to_string()),
671 Value::I32(v) => Ok(v.to_string()),
672 Value::I64(v) => Ok(v.to_string()),
673 Value::F32(v) => Ok(v.to_string()),
674 Value::F64(v) => Ok(v.to_string()),
675 Value::Char(v) => Ok(v.to_string()),
676 Value::String(v) => Ok(v),
677 _ => Ok(format!("!!{}", serde_json::to_string(&self)?)),
678 }
679 }
680
681 pub fn unpack(self) -> EResult<Self> {
682 if let Value::String(ref v) = self {
683 if let Some(s) = v.strip_prefix("!!") {
684 return serde_json::from_str(s).map_err(Into::into);
685 }
686 }
687 Ok(self)
688 }
689
690 fn discriminant(&self) -> usize {
691 match *self {
692 Value::Bool(..) => 0,
693 Value::U8(..) => 1,
694 Value::U16(..) => 2,
695 Value::U32(..) => 3,
696 Value::U64(..) => 4,
697 Value::I8(..) => 5,
698 Value::I16(..) => 6,
699 Value::I32(..) => 7,
700 Value::I64(..) => 8,
701 Value::F32(..) => 9,
702 Value::F64(..) => 10,
703 Value::Char(..) => 11,
704 Value::String(..) => 12,
705 Value::Unit => 13,
706 Value::Option(..) => 14,
707 Value::Newtype(..) => 15,
708 Value::Seq(..) => 16,
709 Value::Map(..) => 17,
710 Value::Bytes(..) => 18,
711 }
712 }
713
714 fn unexpected(&self) -> serde::de::Unexpected {
715 match *self {
716 Value::Bool(b) => serde::de::Unexpected::Bool(b),
717 Value::U8(n) => serde::de::Unexpected::Unsigned(u64::from(n)),
718 Value::U16(n) => serde::de::Unexpected::Unsigned(u64::from(n)),
719 Value::U32(n) => serde::de::Unexpected::Unsigned(u64::from(n)),
720 Value::U64(n) => serde::de::Unexpected::Unsigned(n),
721 Value::I8(n) => serde::de::Unexpected::Signed(i64::from(n)),
722 Value::I16(n) => serde::de::Unexpected::Signed(i64::from(n)),
723 Value::I32(n) => serde::de::Unexpected::Signed(i64::from(n)),
724 Value::I64(n) => serde::de::Unexpected::Signed(n),
725 Value::F32(n) => serde::de::Unexpected::Float(f64::from(n)),
726 Value::F64(n) => serde::de::Unexpected::Float(n),
727 Value::Char(c) => serde::de::Unexpected::Char(c),
728 Value::String(ref s) => serde::de::Unexpected::Str(s),
729 Value::Unit => serde::de::Unexpected::Unit,
730 Value::Option(_) => serde::de::Unexpected::Option,
731 Value::Newtype(_) => serde::de::Unexpected::NewtypeStruct,
732 Value::Seq(_) => serde::de::Unexpected::Seq,
733 Value::Map(_) => serde::de::Unexpected::Map,
734 Value::Bytes(ref b) => serde::de::Unexpected::Bytes(b),
735 }
736 }
737
738 pub fn deserialize_into<'de, T: Deserialize<'de>>(self) -> Result<T, DeserializerError> {
739 T::deserialize(self)
740 }
741 pub fn is_empty(&self) -> bool {
742 match self {
743 Value::Unit => true,
744 Value::Option(v) => v.is_none(),
745 Value::String(s) => s.is_empty(),
746 _ => false,
747 }
748 }
749 #[inline]
750 pub fn is_unit(&self) -> bool {
751 *self == Value::Unit
752 }
753 pub fn is_numeric_type(&self) -> bool {
754 matches!(
755 self,
756 Value::U8(_)
757 | Value::U16(_)
758 | Value::U32(_)
759 | Value::U64(_)
760 | Value::I8(_)
761 | Value::I16(_)
762 | Value::I32(_)
763 | Value::I64(_)
764 | Value::F32(_)
765 | Value::F64(_)
766 )
767 }
768 pub fn is_numeric(&self) -> bool {
769 match self {
770 Value::U8(_)
771 | Value::U16(_)
772 | Value::U32(_)
773 | Value::U64(_)
774 | Value::I8(_)
775 | Value::I16(_)
776 | Value::I32(_)
777 | Value::I64(_)
778 | Value::F32(_)
779 | Value::F64(_) => true,
780 Value::String(v) => v.parse::<f64>().is_ok() || v.parse::<i128>().is_ok(),
781 _ => false,
782 }
783 }
784 pub fn is_seq(&self) -> bool {
785 matches!(self, Value::Seq(_))
786 }
787 pub fn is_map(&self) -> bool {
788 matches!(self, Value::Map(_))
789 }
790 #[cfg(feature = "extended-value")]
791 pub async fn extend(self, timeout: Duration, base: &Path) -> EResult<Value> {
792 let op = crate::op::Op::new(timeout);
793 extend_value(self, &op, base).await
794 }
795}
796
797#[cfg(feature = "extended-value")]
798#[async_recursion::async_recursion]
799async fn extend_value(value: Value, op: &crate::op::Op, base: &Path) -> EResult<Value> {
800 match value {
801 Value::String(s) => Ok(extend_string_value(s, op, base).await?),
802 Value::Seq(s) => {
803 let mut result = Vec::with_capacity(s.len());
804 for val in s {
805 result.push(extend_value(val, op, base).await?);
806 }
807 Ok(Value::Seq(result))
808 }
809 Value::Map(m) => {
810 let mut result = BTreeMap::new();
811 for (k, v) in m {
812 result.insert(k, extend_value(v, op, base).await?);
813 }
814 Ok(Value::Map(result))
815 }
816 _ => Ok(value),
817 }
818}
819
820impl FromStr for Value {
821 type Err = std::convert::Infallible;
822 fn from_str(s: &str) -> Result<Self, Self::Err> {
823 Ok(if let Ok(v) = s.parse::<u64>() {
824 Value::U64(v)
825 } else if let Ok(v) = s.parse::<i64>() {
826 Value::I64(v)
827 } else if let Ok(v) = s.parse::<f64>() {
828 Value::F64(v)
829 } else {
830 serde_json::from_str(s).unwrap_or_else(|_| {
831 let s_l = s.to_lowercase();
832 match s_l.as_str() {
833 "true" => Value::Bool(true),
834 "false" => Value::Bool(false),
835 "none" | "null" => Value::Unit,
836 _ => Value::String(s.to_owned()),
837 }
838 })
839 })
840 }
841}
842
843#[cfg(feature = "extended-value")]
844async fn extend_string_value(val: String, op: &crate::op::Op, base: &Path) -> EResult<Value> {
845 if let Some(s) = val.strip_prefix('^') {
846 let mut sp = s.splitn(2, ' ');
847 let cmd = sp.next().unwrap();
848 macro_rules! pipe {
849 () => {{
850 let cmd = sp
851 .next()
852 .ok_or_else(|| Error::invalid_params("xvalue pipe: command not specified"))?;
853 let cd_cmd = format!("cd \"{}\" && {}", base.to_string_lossy(), cmd);
854 let res = bmart::process::command(
855 "sh",
856 &["-c", &cd_cmd],
857 op.timeout()?,
858 bmart::process::Options::default(),
859 )
860 .await?;
861 if res.ok() {
862 res.out.join("\n")
863 } else {
864 return Err(Error::failed(format!(
865 "xvalue pipe command failed to execute: {}",
866 res.err.join("\n")
867 )));
868 }
869 }};
870 }
871 match cmd {
872 "include" => {
873 let fname = sp.next().ok_or_else(|| {
874 Error::invalid_params("xvalue include: file name not specified")
875 })?;
876 let mut path = base.to_path_buf();
877 path.push(fname);
878 let content = tokio::time::timeout(op.timeout()?, tokio::fs::read(path)).await??;
879 let val: Value = serde_yaml::from_slice(&content).map_err(Error::invalid_data)?;
880 Ok(val)
881 }
882 "include-text" => {
883 let fname = sp.next().ok_or_else(|| {
884 Error::invalid_params("xvalue include: file name not specified")
885 })?;
886 let mut path = base.to_path_buf();
887 path.push(fname);
888 let content =
889 tokio::time::timeout(op.timeout()?, tokio::fs::read_to_string(path)).await??;
890 Ok(Value::String(content.trim_end().to_string()))
891 }
892 "pipe" => {
893 let s = pipe!();
894 let val: Value = serde_yaml::from_str(&s).map_err(Error::invalid_data)?;
895 Ok(val)
896 }
897 "pipe-text" => {
898 let s = pipe!();
899 Ok(Value::String(s.trim_end().to_string()))
900 }
901 _ => Ok(Value::String(if s.starts_with('^') {
902 s.to_owned()
903 } else {
904 val
905 })),
906 }
907 } else {
908 Ok(Value::String(val))
909 }
910}
911
912impl Eq for Value {}
913impl PartialOrd for Value {
914 fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
915 Some(self.cmp(rhs))
916 }
917}
918
919macro_rules! impl_from {
920 ($v: ty, $val: expr) => {
921 impl From<$v> for Value {
922 fn from(src: $v) -> Value {
923 $val(src)
924 }
925 }
926 };
927}
928
929impl_from!(bool, Value::Bool);
930impl_from!(u8, Value::U8);
931impl_from!(i8, Value::I8);
932impl_from!(u16, Value::U16);
933impl_from!(i16, Value::I16);
934impl_from!(u32, Value::U32);
935impl_from!(i32, Value::I32);
936impl_from!(u64, Value::U64);
937impl_from!(i64, Value::I64);
938impl_from!(f32, Value::F32);
939impl_from!(f64, Value::F64);
940impl_from!(String, Value::String);
941
942macro_rules! ngt {
944 ($n: expr, $from: ident, $to: ident) => {
945 if $n > $to::MAX as $from {
946 return Err(Error::invalid_data_static(ERR_TOO_BIG_NUMBER));
947 } else {
948 $n as $to
949 }
950 };
951}
952macro_rules! ngt_nlt {
954 ($n: expr, $from: ident, $to: ident) => {
955 if $n > $to::MAX as $from {
956 return Err(Error::invalid_data_static(ERR_TOO_BIG_NUMBER));
957 } else if $n < $to::MIN as $from {
958 return Err(Error::invalid_data_static(ERR_TOO_SMALL_NUMBER));
959 } else {
960 $n as $to
961 }
962 };
963}
964macro_rules! nltz {
966 ($n: expr, $from: ident, $to: ident) => {
967 if $n < 0 as $from {
968 return Err(Error::invalid_data_static(ERR_TOO_SMALL_NUMBER));
969 } else {
970 $n as $to
971 }
972 };
973}
974
975impl TryFrom<Value> for u8 {
976 type Error = Error;
977
978 fn try_from(value: Value) -> EResult<u8> {
979 match value {
980 Value::Bool(v) => Ok(u8::from(v)),
981 Value::U8(v) => Ok(v),
982 Value::U16(v) => Ok(ngt!(v, u16, u8)),
983 Value::U32(v) => Ok(ngt!(v, u32, u8)),
984 Value::U64(v) => Ok(ngt!(v, u64, u8)),
985 Value::I8(v) => Ok(nltz!(v, i8, u8)),
986 Value::I16(v) => Ok(ngt_nlt!(v, i16, u8)),
987 Value::I32(v) => Ok(ngt_nlt!(v, i32, u8)),
988 Value::I64(v) => Ok(ngt_nlt!(v, i64, u8)),
989 Value::F32(v) => Ok(ngt_nlt!(v, f32, u8)),
990 Value::F64(v) => Ok(ngt_nlt!(v, f64, u8)),
991 Value::String(v) => Ok(v.parse::<u8>()?),
992 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
993 }
994 }
995}
996
997impl TryFrom<&Value> for u8 {
998 type Error = Error;
999
1000 fn try_from(value: &Value) -> EResult<u8> {
1001 match value {
1002 Value::Bool(v) => Ok(u8::from(*v)),
1003 Value::U8(v) => Ok(*v),
1004 Value::U16(v) => Ok(ngt!(*v, u16, u8)),
1005 Value::U32(v) => Ok(ngt!(*v, u32, u8)),
1006 Value::U64(v) => Ok(ngt!(*v, u64, u8)),
1007 Value::I8(v) => Ok(nltz!(*v, i8, u8)),
1008 Value::I16(v) => Ok(ngt_nlt!(*v, i16, u8)),
1009 Value::I32(v) => Ok(ngt_nlt!(*v, i32, u8)),
1010 Value::I64(v) => Ok(ngt_nlt!(*v, i64, u8)),
1011 Value::F32(v) => Ok(ngt_nlt!(*v, f32, u8)),
1012 Value::F64(v) => Ok(ngt_nlt!(*v, f64, u8)),
1013 Value::String(v) => Ok(v.parse::<u8>()?),
1014 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1015 }
1016 }
1017}
1018
1019impl TryFrom<Value> for i8 {
1020 type Error = Error;
1021
1022 fn try_from(value: Value) -> EResult<i8> {
1023 match value {
1024 Value::Bool(v) => Ok(i8::from(v)),
1025 Value::U8(v) => Ok(ngt!(v, u8, i8)),
1026 Value::U16(v) => Ok(ngt!(v, u16, i8)),
1027 Value::U32(v) => Ok(ngt!(v, u32, i8)),
1028 Value::U64(v) => Ok(ngt!(v, u64, i8)),
1029 Value::I8(v) => Ok(v),
1030 Value::I16(v) => Ok(ngt_nlt!(v, i16, i8)),
1031 Value::I32(v) => Ok(ngt_nlt!(v, i32, i8)),
1032 Value::I64(v) => Ok(ngt_nlt!(v, i64, i8)),
1033 Value::F32(v) => Ok(ngt_nlt!(v, f32, i8)),
1034 Value::F64(v) => Ok(ngt_nlt!(v, f64, i8)),
1035 Value::String(v) => Ok(v.parse::<i8>()?),
1036 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1037 }
1038 }
1039}
1040
1041impl TryFrom<&Value> for i8 {
1042 type Error = Error;
1043
1044 fn try_from(value: &Value) -> EResult<i8> {
1045 match value {
1046 Value::Bool(v) => Ok(i8::from(*v)),
1047 Value::U8(v) => Ok(ngt!(*v, u8, i8)),
1048 Value::U16(v) => Ok(ngt!(*v, u16, i8)),
1049 Value::U32(v) => Ok(ngt!(*v, u32, i8)),
1050 Value::U64(v) => Ok(ngt!(*v, u64, i8)),
1051 Value::I8(v) => Ok(*v),
1052 Value::I16(v) => Ok(ngt_nlt!(*v, i16, i8)),
1053 Value::I32(v) => Ok(ngt_nlt!(*v, i32, i8)),
1054 Value::I64(v) => Ok(ngt_nlt!(*v, i64, i8)),
1055 Value::F32(v) => Ok(ngt_nlt!(*v, f32, i8)),
1056 Value::F64(v) => Ok(ngt_nlt!(*v, f64, i8)),
1057 Value::String(v) => Ok(v.parse::<i8>()?),
1058 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1059 }
1060 }
1061}
1062
1063impl TryFrom<Value> for u16 {
1064 type Error = Error;
1065
1066 fn try_from(value: Value) -> EResult<u16> {
1067 match value {
1068 Value::Bool(v) => Ok(u16::from(v)),
1069 Value::U8(v) => Ok(u16::from(v)),
1070 Value::U16(v) => Ok(v),
1071 Value::U32(v) => Ok(ngt!(v, u32, u16)),
1072 Value::U64(v) => Ok(ngt!(v, u64, u16)),
1073 Value::I8(v) => Ok(nltz!(v, i8, u16)),
1074 Value::I16(v) => Ok(nltz!(v, i16, u16)),
1075 Value::I32(v) => Ok(ngt_nlt!(v, i32, u16)),
1076 Value::I64(v) => Ok(ngt_nlt!(v, i64, u16)),
1077 Value::F32(v) => Ok(ngt_nlt!(v, f32, u16)),
1078 Value::F64(v) => Ok(ngt_nlt!(v, f64, u16)),
1079 Value::String(v) => Ok(v.parse::<u16>()?),
1080 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1081 }
1082 }
1083}
1084
1085impl TryFrom<&Value> for u16 {
1086 type Error = Error;
1087
1088 fn try_from(value: &Value) -> EResult<u16> {
1089 match value {
1090 Value::Bool(v) => Ok(u16::from(*v)),
1091 Value::U8(v) => Ok(u16::from(*v)),
1092 Value::U16(v) => Ok(*v),
1093 Value::U32(v) => Ok(ngt!(*v, u32, u16)),
1094 Value::U64(v) => Ok(ngt!(*v, u64, u16)),
1095 Value::I8(v) => Ok(nltz!(*v, i8, u16)),
1096 Value::I16(v) => Ok(nltz!(*v, i16, u16)),
1097 Value::I32(v) => Ok(ngt_nlt!(*v, i32, u16)),
1098 Value::I64(v) => Ok(ngt_nlt!(*v, i64, u16)),
1099 Value::F32(v) => Ok(ngt_nlt!(*v, f32, u16)),
1100 Value::F64(v) => Ok(ngt_nlt!(*v, f64, u16)),
1101 Value::String(v) => Ok(v.parse::<u16>()?),
1102 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1103 }
1104 }
1105}
1106
1107impl TryFrom<Value> for i16 {
1108 type Error = Error;
1109
1110 fn try_from(value: Value) -> EResult<i16> {
1111 match value {
1112 Value::Bool(v) => Ok(i16::from(v)),
1113 Value::U8(v) => Ok(i16::from(v)),
1114 Value::U16(v) => Ok(ngt!(v, u16, i16)),
1115 Value::U32(v) => Ok(ngt!(v, u32, i16)),
1116 Value::U64(v) => Ok(ngt!(v, u64, i16)),
1117 Value::I8(v) => Ok(i16::from(v)),
1118 Value::I16(v) => Ok(v),
1119 Value::I32(v) => Ok(ngt_nlt!(v, i32, i16)),
1120 Value::I64(v) => Ok(ngt_nlt!(v, i64, i16)),
1121 Value::F32(v) => Ok(ngt_nlt!(v, f32, i16)),
1122 Value::F64(v) => Ok(ngt_nlt!(v, f64, i16)),
1123 Value::String(v) => Ok(v.parse::<i16>()?),
1124 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1125 }
1126 }
1127}
1128
1129impl TryFrom<&Value> for i16 {
1130 type Error = Error;
1131
1132 fn try_from(value: &Value) -> EResult<i16> {
1133 match value {
1134 Value::Bool(v) => Ok(i16::from(*v)),
1135 Value::U8(v) => Ok(i16::from(*v)),
1136 Value::U16(v) => Ok(ngt!(*v, u16, i16)),
1137 Value::U32(v) => Ok(ngt!(*v, u32, i16)),
1138 Value::U64(v) => Ok(ngt!(*v, u64, i16)),
1139 Value::I8(v) => Ok(i16::from(*v)),
1140 Value::I16(v) => Ok(*v),
1141 Value::I32(v) => Ok(ngt_nlt!(*v, i32, i16)),
1142 Value::I64(v) => Ok(ngt_nlt!(*v, i64, i16)),
1143 Value::F32(v) => Ok(ngt_nlt!(*v, f32, i16)),
1144 Value::F64(v) => Ok(ngt_nlt!(*v, f64, i16)),
1145 Value::String(v) => Ok(v.parse::<i16>()?),
1146 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1147 }
1148 }
1149}
1150
1151impl TryFrom<Value> for u32 {
1152 type Error = Error;
1153
1154 fn try_from(value: Value) -> EResult<u32> {
1155 match value {
1156 Value::Bool(v) => Ok(u32::from(v)),
1157 Value::U8(v) => Ok(u32::from(v)),
1158 Value::U16(v) => Ok(u32::from(v)),
1159 Value::U32(v) => Ok(v),
1160 Value::U64(v) => Ok(ngt!(v, u64, u32)),
1161 Value::I8(v) => Ok(nltz!(v, i8, u32)),
1162 Value::I16(v) => Ok(nltz!(v, i16, u32)),
1163 Value::I32(v) => Ok(nltz!(v, i32, u32)),
1164 Value::I64(v) => Ok(ngt_nlt!(v, i64, u32)),
1165 Value::F32(v) => Ok(nltz!(v, f32, u32)),
1166 Value::F64(v) => Ok(ngt_nlt!(v, f64, u32)),
1167 Value::String(v) => Ok(v.parse::<u32>()?),
1168 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1169 }
1170 }
1171}
1172
1173impl TryFrom<&Value> for u32 {
1174 type Error = Error;
1175
1176 fn try_from(value: &Value) -> EResult<u32> {
1177 match value {
1178 Value::Bool(v) => Ok(u32::from(*v)),
1179 Value::U8(v) => Ok(u32::from(*v)),
1180 Value::U16(v) => Ok(u32::from(*v)),
1181 Value::U32(v) => Ok(*v),
1182 Value::U64(v) => Ok(ngt!(*v, u64, u32)),
1183 Value::I8(v) => Ok(nltz!(*v, i8, u32)),
1184 Value::I16(v) => Ok(nltz!(*v, i16, u32)),
1185 Value::I32(v) => Ok(nltz!(*v, i32, u32)),
1186 Value::I64(v) => Ok(ngt_nlt!(*v, i64, u32)),
1187 Value::F32(v) => Ok(nltz!(*v, f32, u32)),
1188 Value::F64(v) => Ok(ngt_nlt!(*v, f64, u32)),
1189 Value::String(v) => Ok(v.parse::<u32>()?),
1190 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1191 }
1192 }
1193}
1194
1195impl TryFrom<Value> for i32 {
1196 type Error = Error;
1197
1198 fn try_from(value: Value) -> EResult<i32> {
1199 match value {
1200 Value::Bool(v) => Ok(i32::from(v)),
1201 Value::U8(v) => Ok(i32::from(v)),
1202 Value::U16(v) => Ok(i32::from(v)),
1203 Value::U32(v) => Ok(ngt!(v, u32, i32)),
1204 Value::U64(v) => Ok(ngt!(v, u64, i32)),
1205 Value::I8(v) => Ok(i32::from(v)),
1206 Value::I16(v) => Ok(i32::from(v)),
1207 Value::I32(v) => Ok(v),
1208 Value::I64(v) => Ok(ngt_nlt!(v, i64, i32)),
1209 #[allow(clippy::cast_possible_truncation)]
1210 Value::F32(v) => Ok(v as i32),
1211 Value::F64(v) => Ok(ngt_nlt!(v, f64, i32)),
1212 Value::String(v) => Ok(v.parse::<i32>()?),
1213 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1214 }
1215 }
1216}
1217
1218impl TryFrom<&Value> for i32 {
1219 type Error = Error;
1220
1221 fn try_from(value: &Value) -> EResult<i32> {
1222 match value {
1223 Value::Bool(v) => Ok(i32::from(*v)),
1224 Value::U8(v) => Ok(i32::from(*v)),
1225 Value::U16(v) => Ok(i32::from(*v)),
1226 Value::U32(v) => Ok(ngt!(*v, u32, i32)),
1227 Value::U64(v) => Ok(ngt!(*v, u64, i32)),
1228 Value::I8(v) => Ok(i32::from(*v)),
1229 Value::I16(v) => Ok(i32::from(*v)),
1230 Value::I32(v) => Ok(*v),
1231 Value::I64(v) => Ok(ngt_nlt!(*v, i64, i32)),
1232 #[allow(clippy::cast_possible_truncation)]
1233 Value::F32(v) => Ok(*v as i32),
1234 Value::F64(v) => Ok(ngt_nlt!(*v, f64, i32)),
1235 Value::String(v) => Ok(v.parse::<i32>()?),
1236 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1237 }
1238 }
1239}
1240
1241impl TryFrom<&Value> for u64 {
1242 type Error = Error;
1243
1244 fn try_from(value: &Value) -> EResult<u64> {
1245 match value {
1246 Value::Bool(v) => Ok(u64::from(*v)),
1247 Value::U8(v) => Ok(u64::from(*v)),
1248 Value::U16(v) => Ok(u64::from(*v)),
1249 Value::U32(v) => Ok(u64::from(*v)),
1250 Value::U64(v) => Ok(*v),
1251 Value::I8(v) => Ok(nltz!(*v, i8, u64)),
1252 Value::I16(v) => Ok(nltz!(*v, i16, u64)),
1253 Value::I32(v) => Ok(nltz!(*v, i32, u64)),
1254 Value::I64(v) => Ok(nltz!(*v, i64, u64)),
1255 Value::F32(v) => Ok(nltz!(*v, f32, u64)),
1256 Value::F64(v) => Ok(nltz!(*v, f64, u64)),
1257 Value::String(v) => Ok(v.parse::<u64>()?),
1258 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1259 }
1260 }
1261}
1262
1263impl TryFrom<Value> for u64 {
1264 type Error = Error;
1265
1266 fn try_from(value: Value) -> EResult<u64> {
1267 match value {
1268 Value::Bool(v) => Ok(u64::from(v)),
1269 Value::U8(v) => Ok(u64::from(v)),
1270 Value::U16(v) => Ok(u64::from(v)),
1271 Value::U32(v) => Ok(u64::from(v)),
1272 Value::U64(v) => Ok(v),
1273 Value::I8(v) => Ok(nltz!(v, i8, u64)),
1274 Value::I16(v) => Ok(nltz!(v, i16, u64)),
1275 Value::I32(v) => Ok(nltz!(v, i32, u64)),
1276 Value::I64(v) => Ok(nltz!(v, i64, u64)),
1277 Value::F32(v) => Ok(nltz!(v, f32, u64)),
1278 Value::F64(v) => Ok(nltz!(v, f64, u64)),
1279 Value::String(v) => Ok(v.parse::<u64>()?),
1280 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1281 }
1282 }
1283}
1284
1285impl TryFrom<&Value> for i64 {
1286 type Error = Error;
1287
1288 fn try_from(value: &Value) -> EResult<i64> {
1289 match value {
1290 Value::Bool(v) => Ok(i64::from(*v)),
1291 Value::U8(v) => Ok(i64::from(*v)),
1292 Value::U16(v) => Ok(i64::from(*v)),
1293 Value::U32(v) => Ok(i64::from(*v)),
1294 Value::U64(v) => Ok(ngt!(*v, u64, i64)),
1295 Value::I8(v) => Ok(i64::from(*v)),
1296 Value::I16(v) => Ok(i64::from(*v)),
1297 Value::I32(v) => Ok(i64::from(*v)),
1298 Value::I64(v) => Ok(*v),
1299 #[allow(clippy::cast_possible_truncation)]
1300 Value::F32(v) => Ok(*v as i64),
1301 #[allow(clippy::cast_possible_truncation)]
1302 Value::F64(v) => Ok(*v as i64),
1303 Value::String(v) => Ok(v.parse::<i64>()?),
1304 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1305 }
1306 }
1307}
1308
1309impl TryFrom<Value> for i64 {
1310 type Error = Error;
1311
1312 fn try_from(value: Value) -> EResult<i64> {
1313 match value {
1314 Value::Bool(v) => Ok(i64::from(v)),
1315 Value::U8(v) => Ok(i64::from(v)),
1316 Value::U16(v) => Ok(i64::from(v)),
1317 Value::U32(v) => Ok(i64::from(v)),
1318 Value::U64(v) => Ok(ngt!(v, u64, i64)),
1319 Value::I8(v) => Ok(i64::from(v)),
1320 Value::I16(v) => Ok(i64::from(v)),
1321 Value::I32(v) => Ok(i64::from(v)),
1322 Value::I64(v) => Ok(v),
1323 #[allow(clippy::cast_possible_truncation)]
1324 Value::F32(v) => Ok(v as i64),
1325 #[allow(clippy::cast_possible_truncation)]
1326 Value::F64(v) => Ok(v as i64),
1327 Value::String(v) => Ok(v.parse::<i64>()?),
1328 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1329 }
1330 }
1331}
1332
1333impl TryFrom<Value> for f32 {
1334 type Error = Error;
1335
1336 fn try_from(value: Value) -> EResult<f32> {
1337 match value {
1338 Value::Bool(v) => Ok(float_from_bool!(v)),
1339 Value::F32(v) => Ok(v),
1340 Value::F64(v) => Ok(ngt_nlt!(v, f64, f32)),
1341 Value::U8(v) => Ok(f32::from(v)),
1342 Value::U16(v) => Ok(f32::from(v)),
1343 Value::U32(v) => Ok(ngt!(v, u32, f32)),
1344 Value::U64(v) => Ok(ngt!(v, u64, f32)),
1345 Value::I8(v) => Ok(f32::from(v)),
1346 Value::I16(v) => Ok(f32::from(v)),
1347 Value::I32(v) => Ok(ngt_nlt!(v, i32, f32)),
1348 Value::I64(v) => Ok(ngt_nlt!(v, i64, f32)),
1349 Value::String(v) => Ok(v.parse::<f32>()?),
1350 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1351 }
1352 }
1353}
1354
1355impl TryFrom<&Value> for f32 {
1356 type Error = Error;
1357
1358 fn try_from(value: &Value) -> EResult<f32> {
1359 match value {
1360 Value::Bool(v) => Ok(float_from_bool!(*v)),
1361 Value::F32(v) => Ok(*v),
1362 Value::F64(v) => Ok(ngt_nlt!(*v, f64, f32)),
1363 Value::U8(v) => Ok(f32::from(*v)),
1364 Value::U16(v) => Ok(f32::from(*v)),
1365 Value::U32(v) => Ok(ngt!(*v, u32, f32)),
1366 Value::U64(v) => Ok(ngt!(*v, u64, f32)),
1367 Value::I8(v) => Ok(f32::from(*v)),
1368 Value::I16(v) => Ok(f32::from(*v)),
1369 Value::I32(v) => Ok(ngt_nlt!(*v, i32, f32)),
1370 Value::I64(v) => Ok(ngt_nlt!(*v, i64, f32)),
1371 Value::String(v) => Ok(v.parse::<f32>()?),
1372 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1373 }
1374 }
1375}
1376
1377impl TryFrom<&Value> for f64 {
1378 type Error = Error;
1379
1380 fn try_from(value: &Value) -> EResult<f64> {
1381 match value {
1382 Value::Bool(v) => Ok(float_from_bool!(*v)),
1383 Value::U8(v) => Ok(f64::from(*v)),
1384 Value::U16(v) => Ok(f64::from(*v)),
1385 Value::U32(v) => Ok(f64::from(*v)),
1386 Value::U64(v) => Ok(ngt!(*v, u64, f64)),
1387 Value::I8(v) => Ok(f64::from(*v)),
1388 Value::I16(v) => Ok(f64::from(*v)),
1389 Value::I32(v) => Ok(f64::from(*v)),
1390 Value::I64(v) => Ok(ngt_nlt!(*v, i64, f64)),
1391 Value::F32(v) => Ok(f64::from(*v)),
1392 Value::F64(v) => Ok(*v),
1393 Value::String(v) => Ok(v.parse::<f64>()?),
1394 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1395 }
1396 }
1397}
1398
1399impl TryFrom<Value> for f64 {
1400 type Error = Error;
1401
1402 fn try_from(value: Value) -> EResult<f64> {
1403 match value {
1404 Value::Bool(v) => Ok(float_from_bool!(v)),
1405 Value::U8(v) => Ok(f64::from(v)),
1406 Value::U16(v) => Ok(f64::from(v)),
1407 Value::U32(v) => Ok(f64::from(v)),
1408 Value::U64(v) => Ok(ngt!(v, u64, f64)),
1409 Value::I8(v) => Ok(f64::from(v)),
1410 Value::I16(v) => Ok(f64::from(v)),
1411 Value::I32(v) => Ok(f64::from(v)),
1412 Value::I64(v) => Ok(ngt_nlt!(v, i64, f64)),
1413 Value::F32(v) => Ok(f64::from(v)),
1414 Value::F64(v) => Ok(v),
1415 Value::String(v) => Ok(v.parse::<f64>()?),
1416 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1417 }
1418 }
1419}
1420
1421impl TryFrom<Value> for Option<std::time::Duration> {
1422 type Error = Error;
1423
1424 fn try_from(v: Value) -> EResult<Option<std::time::Duration>> {
1425 let t: f64 = v.try_into()?;
1426 if t > 0.0 {
1427 Ok(Some(std::time::Duration::from_secs_f64(t)))
1428 } else {
1429 Ok(None)
1430 }
1431 }
1432}
1433
1434impl TryFrom<Value> for String {
1435 type Error = Error;
1436
1437 fn try_from(v: Value) -> EResult<String> {
1438 match v {
1439 Value::Option(Some(s)) => Ok((*s).try_into()?),
1440 Value::String(s) => Ok(s),
1441 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1442 }
1443 }
1444}
1445
1446impl TryFrom<&Value> for String {
1447 type Error = Error;
1448
1449 fn try_from(v: &Value) -> EResult<String> {
1450 match v {
1451 Value::Option(Some(s)) => Ok(s.as_ref().try_into()?),
1452 Value::String(s) => Ok(s.clone()),
1453 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1454 }
1455 }
1456}
1457
1458impl<'a> TryFrom<&'a Value> for &'a str {
1459 type Error = Error;
1460
1461 fn try_from(v: &'a Value) -> EResult<&'a str> {
1462 match v {
1463 Value::Option(Some(s)) => Ok(s.as_ref().try_into()?),
1464 Value::String(s) => Ok(s),
1465 _ => Err(Error::invalid_data_static(ERR_INVALID_VALUE)),
1466 }
1467 }
1468}
1469
1470impl TryFrom<Value> for Option<String> {
1471 type Error = Error;
1472
1473 fn try_from(v: Value) -> EResult<Option<String>> {
1474 let s = match v {
1475 Value::Option(v) => match v {
1476 Some(s) => (*s).try_into()?,
1477 None => return Ok(None),
1478 },
1479 Value::Unit => return Ok(None),
1480 Value::String(s) => s,
1481 _ => {
1482 return Err(Error::invalid_data_static(ERR_INVALID_VALUE));
1483 }
1484 };
1485 Ok(if s.is_empty() { None } else { Some(s) })
1486 }
1487}
1488
1489impl TryFrom<Value> for std::time::Duration {
1490 type Error = Error;
1491
1492 fn try_from(v: Value) -> EResult<std::time::Duration> {
1493 Ok(std::time::Duration::from_secs_f64(v.try_into()?))
1494 }
1495}
1496
1497impl TryFrom<Value> for Vec<Value> {
1498 type Error = Error;
1499
1500 fn try_from(value: Value) -> EResult<Vec<Value>> {
1501 match value {
1502 Value::Seq(vec) => Ok(vec),
1503 Value::String(s) => Ok(s.split(',').map(|s| Value::String(s.to_owned())).collect()),
1504 _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1505 }
1506 }
1507}
1508
1509impl<S: BuildHasher + Default> TryFrom<Value> for HashSet<Value, S> {
1510 type Error = Error;
1511
1512 fn try_from(value: Value) -> EResult<HashSet<Value, S>> {
1513 match value {
1514 Value::Seq(vec) => Ok(HashSet::from_iter(vec)),
1515 Value::String(s) => Ok(s.split(',').map(|s| Value::String(s.to_owned())).collect()),
1516 _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1517 }
1518 }
1519}
1520
1521impl From<HashSet<ipnetwork::IpNetwork>> for Value {
1522 fn from(v: HashSet<ipnetwork::IpNetwork>) -> Value {
1523 to_value(v).unwrap()
1524 }
1525}
1526
1527impl<S: BuildHasher + Default> TryFrom<Value> for HashSet<ipnetwork::IpNetwork, S> {
1528 type Error = Error;
1529
1530 fn try_from(value: Value) -> EResult<HashSet<ipnetwork::IpNetwork, S>> {
1531 match value {
1532 Value::Seq(vec) => {
1533 let mut result = HashSet::default();
1534 for v in vec {
1535 result.insert(v.deserialize_into()?);
1536 }
1537 Ok(result)
1538 }
1539 Value::String(s) => {
1540 let mut result = HashSet::default();
1541 for v in s.split(',') {
1542 result.insert(v.parse()?);
1543 }
1544 Ok(result)
1545 }
1546 _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1547 }
1548 }
1549}
1550
1551impl TryFrom<Value> for Vec<String> {
1552 type Error = Error;
1553
1554 fn try_from(value: Value) -> EResult<Vec<String>> {
1555 match value {
1556 Value::Seq(vec) => {
1557 let mut result = Vec::new();
1558 for v in vec {
1559 result.push(v.try_into()?);
1560 }
1561 Ok(result)
1562 }
1563 Value::String(s) => Ok(s.split(',').map(ToOwned::to_owned).collect()),
1564 _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1565 }
1566 }
1567}
1568
1569impl TryFrom<&Value> for Vec<String> {
1570 type Error = Error;
1571
1572 fn try_from(value: &Value) -> EResult<Vec<String>> {
1573 match value {
1574 Value::Seq(vec) => {
1575 let mut result = Vec::new();
1576 for v in vec {
1577 result.push(v.try_into()?);
1578 }
1579 Ok(result)
1580 }
1581 Value::String(s) => Ok(s.split(',').map(ToOwned::to_owned).collect()),
1582 _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1583 }
1584 }
1585}
1586
1587impl<'a> TryFrom<&'a Value> for Vec<&'a str> {
1588 type Error = Error;
1589
1590 fn try_from(value: &'a Value) -> EResult<Vec<&'a str>> {
1591 match value {
1592 Value::Seq(vec) => {
1593 let mut result = Vec::new();
1594 for v in vec {
1595 result.push(v.try_into()?);
1596 }
1597 Ok(result)
1598 }
1599 Value::String(s) => Ok(s.split(',').collect()),
1600 _ => Err(Error::invalid_data_static(ERR_EXPECTED_VEC_OR_STRING)),
1601 }
1602 }
1603}
1604
1605impl TryFrom<Value> for bool {
1606 type Error = Error;
1607
1608 fn try_from(value: Value) -> EResult<bool> {
1609 match value {
1610 Value::Bool(v) => Ok(v),
1611 Value::String(s) => match s.to_lowercase().as_str() {
1612 "true" | "1" | "yes" => Ok(true),
1613 "false" | "0" | "no" => Ok(false),
1614 _ => Err(Error::invalid_data_static(ERR_INVALID_BOOLEAN_VALUE)),
1615 },
1616 _ => {
1617 let n: u64 = value
1618 .try_into()
1619 .map_err(|_| Error::invalid_data_static(ERR_INVALID_BOOLEAN_VALUE))?;
1620 if n == 0 {
1621 Ok(false)
1622 } else if n == 1 {
1623 Ok(true)
1624 } else {
1625 Err(Error::invalid_data_static(ERR_INVALID_BOOLEAN_VALUE))
1626 }
1627 }
1628 }
1629 }
1630}
1631
1632impl From<&str> for Value {
1633 fn from(s: &str) -> Value {
1634 Value::String(s.to_owned())
1635 }
1636}
1637
1638impl From<&String> for Value {
1639 fn from(s: &String) -> Value {
1640 Value::String(s.clone())
1641 }
1642}
1643
1644impl From<Vec<Value>> for Value {
1645 fn from(v: Vec<Value>) -> Value {
1646 Value::Seq(v)
1647 }
1648}
1649
1650impl From<HashSet<Value>> for Value {
1651 fn from(v: HashSet<Value>) -> Value {
1652 Value::Seq(Vec::from_iter(v))
1653 }
1654}
1655
1656impl From<Vec<String>> for Value {
1657 fn from(v: Vec<String>) -> Value {
1658 Value::Seq(v.iter().map(Into::into).collect::<Vec<Value>>())
1659 }
1660}
1661
1662impl From<BTreeMap<Value, Value>> for Value {
1663 fn from(v: BTreeMap<Value, Value>) -> Value {
1664 Value::Map(v)
1665 }
1666}
1667
1668impl From<std::time::Duration> for Value {
1669 fn from(v: std::time::Duration) -> Value {
1670 v.as_secs_f64().into()
1671 }
1672}
1673
1674impl From<Option<std::time::Duration>> for Value {
1675 fn from(v: Option<std::time::Duration>) -> Value {
1676 v.map_or(Value::Unit, |d| d.as_secs_f64().into())
1677 }
1678}
1679
1680impl From<Option<f64>> for Value {
1681 fn from(v: Option<f64>) -> Value {
1682 v.map_or(Value::Unit, Value::F64)
1683 }
1684}
1685
1686impl From<Option<String>> for Value {
1687 fn from(v: Option<String>) -> Value {
1688 v.map_or(Value::Unit, Into::into)
1689 }
1690}
1691
1692impl TryFrom<Value> for serde_json::Value {
1693 type Error = Error;
1694 fn try_from(v: Value) -> EResult<Self> {
1695 serde_json::to_value(v).map_err(Into::into)
1696 }
1697}
1698
1699impl TryFrom<serde_json::Value> for Value {
1700 type Error = Error;
1701 fn try_from(v: serde_json::Value) -> EResult<Self> {
1702 serde_json::from_value(v).map_err(Into::into)
1703 }
1704}
1705
1706#[cfg(test)]
1707mod test {
1708 use crate::prelude::*;
1709 use serde::Serialize;
1710
1711 #[test]
1712 fn test_val_pack() -> EResult<()> {
1713 #[derive(Serialize)]
1714 struct My {
1715 test: bool,
1716 abc: usize,
1717 }
1718
1719 let my = My {
1720 test: true,
1721 abc: 123,
1722 };
1723 let mut valx: Value = to_value(my)?;
1724 valx = valx.unpack()?;
1725 let vlstr = valx.clone().to_string_or_pack()?;
1726 dbg!(&vlstr);
1727 let mut val = Value::String(vlstr);
1728 val = val.unpack()?;
1729 assert_eq!(val, valx);
1730 Ok(())
1731 }
1732
1733 #[test]
1734 fn test_val_parse() {
1735 let val: Value = "12345.111".parse().unwrap();
1736 assert_eq!(val, Value::F64(12345.111));
1737 let val: Value = "12345".parse().unwrap();
1738 assert_eq!(val, Value::U64(12345));
1739 let val: Value = "-12345".parse().unwrap();
1740 assert_eq!(val, Value::I64(-12345));
1741 let val: Value = "True".parse().unwrap();
1742 assert_eq!(val, Value::Bool(true));
1743 let val: Value = "False".parse().unwrap();
1744 assert_eq!(val, Value::Bool(false));
1745 let val: Value = "None".parse().unwrap();
1746 assert_eq!(val, Value::Unit);
1747 let val: Value = "Null".parse().unwrap();
1748 assert_eq!(val, Value::Unit);
1749 }
1750}