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