1use std::borrow::Cow;
2use std::fmt::Display;
3use std::hash::Hash;
4use std::str::{self, FromStr};
5use std::{io, mem};
6
7use thiserror::Error;
8
9use crate::ValueRef;
10
11
12macro_rules! param_value_int {
13 ($val:ty) => {
14 impl From<$val> for Value {
15 fn from(value: $val) -> Self {
16 Self::Int(value as i64)
17 }
18 }
19
20 impl From<&$val> for Value {
21 fn from(value: &$val) -> Self {
22 Self::Int(*value as i64)
23 }
24 }
25
26 impl From<Option<$val>> for Value {
27 fn from(value: Option<$val>) -> Self {
28 if let Some(v) = value {
29 Self::Int(v as i64)
30 } else {
31 Self::Empty
32 }
33 }
34 }
35 };
36}
37
38macro_rules! param_value_float {
39 ($val:ty) => {
40 impl From<$val> for Value {
41 fn from(value: $val) -> Self {
42 Self::Float(value as f64)
43 }
44 }
45
46 impl From<&$val> for Value {
47 fn from(value: &$val) -> Self {
48 Self::Float(*value as f64)
49 }
50 }
51
52 impl From<Option<$val>> for Value {
53 fn from(value: Option<$val>) -> Self {
54 if let Some(v) = value {
55 Self::Float(v as f64)
56 } else {
57 Self::Empty
58 }
59 }
60 }
61 };
62}
63#[derive(Debug, Clone, PartialEq, PartialOrd, Default)]
68#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
69pub enum Value {
70 String(String),
72 Float(f64),
74 Int(i64),
76 Buffer(Box<[u8]>),
78 Boolean(bool),
80 #[default]
82 Empty,
83 List(Box<[Value]>),
85}
86
87impl Eq for Value {}
88
89impl From<String> for Value {
90 fn from(value: String) -> Self {
91 Value::new(value)
92 }
93}
94
95impl From<&str> for Value {
96 fn from(value: &str) -> Self {
97 Value::wrap(value)
98 }
99}
100
101impl From<Cow<'_, str>> for Value {
102 fn from(value: Cow<'_, str>) -> Self {
103 Value::wrap(&value)
104 }
105}
106
107pub trait ParamValue {
110 fn is_empty(&self) -> bool;
112
113 fn is_i64(&self) -> bool;
115
116 fn is_f64(&self) -> bool;
120
121 fn is_buffer(&self) -> bool;
123
124 fn is_str(&self) -> bool;
127
128 fn is_numeric(&self) -> bool {
130 self.is_i64() | self.is_f64()
131 }
132
133 fn is_list(&self) -> bool;
135
136 fn is_boolean(&self) -> bool;
138
139 fn to_f64(&self) -> Result<f64, ParamValueParseError>;
141
142 fn to_f32(&self) -> Result<f32, ParamValueParseError> {
144 let v = self.to_f64()?;
145 Ok(v as f32)
146 }
147
148 fn to_bool(&self) -> Result<bool, ParamValueParseError>;
150
151 fn to_i64(&self) -> Result<i64, ParamValueParseError>;
153
154 fn to_i32(&self) -> Result<i32, ParamValueParseError> {
156 let v = self.to_i64()?;
157 Ok(v as i32)
158 }
159
160 fn to_u64(&self) -> Result<u64, ParamValueParseError> {
162 let v = self.to_i64()?;
163 Ok(v as u64)
164 }
165
166 fn to_str(&self) -> Cow<'_, str>;
168
169 fn as_str(&self) -> Cow<'_, str> {
171 self.to_str()
172 }
173
174 fn to_buffer(&self) -> Result<Cow<'_, [u8]>, ParamValueParseError>;
180
181 fn as_slice(&self) -> Cow<'_, [Value]>;
183
184 fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
186
187 fn as_bytes(&self) -> Cow<'_, [u8]>;
190
191 fn as_ref(&self) -> crate::ValueRef<'_>;
193
194 fn data_len(&self) -> usize;
196}
197
198#[derive(Debug, Clone, Error, PartialEq)]
201pub enum ParamValueParseError {
202 #[error("Failed to extract a float from {0:?}")]
204 FailedToExtractFloat(Option<String>),
205 #[error("Failed to extract a int from {0:?}")]
207 FailedToExtractInt(Option<String>),
208 #[error("Failed to extract a string")]
210 FailedToExtractString,
211 #[error("Failed to extract a buffer")]
213 FailedToExtractBuffer,
214}
215
216impl FromStr for Value {
220 type Err = ParamValueParseError;
221
222 fn from_str(s: &str) -> Result<Self, Self::Err> {
223 if s.is_empty() {
224 return Ok(Self::Empty);
225 }
226 if let Ok(value) = s.parse::<i64>() {
227 Ok(Self::Int(value))
228 } else if let Ok(value) = s.parse::<f64>() {
229 Ok(Self::Float(value))
230 } else if let Ok(value) = s.parse::<bool>() {
231 Ok(Self::Boolean(value))
232 } else {
233 Ok(Self::String(s.to_string()))
234 }
235 }
236}
237
238impl Display for Value {
239 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240 match self {
241 Value::String(v) => f.write_str(v),
242 Value::Float(v) => v.fmt(f),
243 Value::Int(v) => v.fmt(f),
244 Value::Buffer(v) => f.write_str(&String::from_utf8_lossy(v)),
245 Value::Empty => f.write_str(""),
246 Value::Boolean(v) => v.fmt(f),
247 Value::List(v) => {
248 f.write_str("[ ")?;
249 if let Some(vi) = v.first() {
250 vi.fmt(f)?;
251 }
252 for vi in v.iter().skip(1) {
253 f.write_str(", ")?;
254 vi.fmt(f)?;
255 }
256 f.write_str(" ]")
257 }
258 }
259 }
260}
261
262impl From<ParamValueParseError> for io::Error {
263 fn from(value: ParamValueParseError) -> Self {
264 Self::new(io::ErrorKind::InvalidData, value)
265 }
266}
267
268impl Value {
269 pub fn new(s: String) -> Self {
276 if s.is_empty() {
277 Self::Empty
278 } else if let Ok(value) = s.parse::<i64>() {
279 Self::Int(value)
280 } else if let Ok(value) = s.parse::<f64>() {
281 Self::Float(value)
282 } else if let Ok(value) = s.parse::<bool>() {
283 Self::Boolean(value)
284 } else {
285 Self::String(s)
286 }
287 }
288
289 pub fn wrap(s: &str) -> Self {
296 if s.is_empty() {
297 Self::Empty
298 } else if let Ok(value) = s.parse::<i64>() {
299 Self::Int(value)
300 } else if let Ok(value) = s.parse::<f64>() {
301 Self::Float(value)
302 } else {
303 Self::String(s.to_string())
304 }
305 }
306
307 pub fn is_empty(&self) -> bool {
309 matches!(self, Self::Empty)
310 }
311
312 pub fn is_i64(&self) -> bool {
314 matches!(self, Self::Int(_))
315 }
316
317 pub fn is_f64(&self) -> bool {
319 matches!(self, Self::Float(_))
320 }
321
322 pub fn is_buffer(&self) -> bool {
324 matches!(self, Self::Buffer(_))
325 }
326
327 pub fn is_str(&self) -> bool {
329 matches!(self, Self::String(_))
330 }
331
332 pub fn is_list(&self) -> bool {
334 matches!(self, Self::List(_))
335 }
336
337 pub fn coerce_f64(&mut self) -> Result<(), ParamValueParseError> {
339 let value = self.to_f64()?;
340 *self = Self::Float(value);
341 Ok(())
342 }
343
344 pub fn coerce_i64(&mut self) -> Result<(), ParamValueParseError> {
346 let value = self.to_i64()?;
347 *self = Self::Int(value);
348 Ok(())
349 }
350
351 pub fn coerce_str(&mut self) -> Result<(), ParamValueParseError> {
353 let value = self.to_string();
354 *self = Self::String(value);
355 Ok(())
356 }
357
358 pub fn coerce_empty(&mut self) {
360 *self = Self::Empty;
361 }
362
363 pub fn coerce_buffer(&mut self) -> Result<(), ParamValueParseError> {
365 let buffer = self.to_buffer()?;
366 *self = Self::Buffer(buffer.into());
367 Ok(())
368 }
369
370 pub fn coerce_bool(&mut self) -> Result<(), ParamValueParseError> {
372 let value = self.to_bool()?;
373 *self = Self::Boolean(value);
374 Ok(())
375 }
376
377 pub fn coerce_list(&mut self) -> Result<(), ParamValueParseError> {
379 if !self.is_list() {
380 let mut tmp = Self::Empty;
381 core::mem::swap(&mut tmp, self);
382 *self = Self::List([tmp].into());
383 }
384 Ok(())
385 }
386
387 pub fn parse<T: FromStr>(&self) -> Result<T, T::Err> {
391 match self {
392 Value::String(s) => s.parse(),
393 Value::Float(v) => v.to_string().parse(),
394 Value::Int(i) => i.to_string().parse(),
395 Value::Buffer(b) => String::from_utf8_lossy(b).parse(),
396 Value::Empty => "".parse(),
397 Value::Boolean(b) => b.to_string().parse(),
398 Value::List(_) => self.to_string().parse(),
399 }
400 }
401
402 pub fn to_bool(&self) -> Result<bool, ParamValueParseError> {
404 if let Self::Boolean(val) = self {
405 Ok(*val)
406 } else if self.is_numeric() {
407 Ok(self.to_i64()? != 0)
408 } else if let Self::Empty = self {
409 Ok(false)
410 } else if let Ok(v) = self.parse() {
411 Ok(v)
412 } else {
413 Err(ParamValueParseError::FailedToExtractInt(Some(
414 self.to_string(),
415 )))
416 }
417 }
418
419 pub fn to_f64(&self) -> Result<f64, ParamValueParseError> {
421 if let Self::Float(val) = self {
422 return Ok(*val);
423 } else if let Self::Int(val) = self {
424 return Ok(*val as f64);
425 } else if let Self::String(val) = self {
426 if let Ok(v) = val.parse() {
427 return Ok(v);
428 }
429 }
430 Err(ParamValueParseError::FailedToExtractFloat(Some(
431 self.to_string(),
432 )))
433 }
434
435 pub fn to_i64(&self) -> Result<i64, ParamValueParseError> {
437 if let Self::Int(val) = self {
438 return Ok(*val);
439 } else if let Self::Float(val) = self {
440 return Ok(*val as i64);
441 } else if let Self::String(val) = self {
442 if let Ok(v) = val.parse() {
443 return Ok(v);
444 }
445 }
446 Err(ParamValueParseError::FailedToExtractInt(Some(
447 self.to_string(),
448 )))
449 }
450
451 pub fn to_str(&self) -> Cow<'_, str> {
453 if let Self::String(val) = self {
454 Cow::Borrowed(val)
455 } else {
456 Cow::Owned(self.to_string())
457 }
458 }
459
460 pub fn to_buffer(&self) -> Result<Cow<'_, [u8]>, ParamValueParseError> {
462 if let Self::Buffer(val) = self {
463 Ok(Cow::Borrowed(val))
464 } else if let Self::String(val) = self {
465 Ok(Cow::Borrowed(val.as_bytes()))
466 } else {
467 Err(ParamValueParseError::FailedToExtractBuffer)
468 }
469 }
470
471 pub fn as_ref(&self) -> ValueRef<'_> {
473 self.into()
474 }
475
476 pub fn as_slice(&self) -> &[Self] {
478 if let Self::List(val) = self {
479 val.as_ref()
480 } else {
481 core::slice::from_ref(self)
482 }
483 }
484}
485
486impl ParamValue for Value {
487 fn is_empty(&self) -> bool {
488 self.is_empty()
489 }
490
491 fn is_i64(&self) -> bool {
492 self.is_i64()
493 }
494
495 fn is_f64(&self) -> bool {
496 self.is_f64()
497 }
498
499 fn is_buffer(&self) -> bool {
500 self.is_buffer()
501 }
502
503 fn is_str(&self) -> bool {
504 self.is_str()
505 }
506
507 fn to_f64(&self) -> Result<f64, ParamValueParseError> {
508 self.to_f64()
509 }
510
511 fn to_i64(&self) -> Result<i64, ParamValueParseError> {
512 self.to_i64()
513 }
514
515 fn to_str(&self) -> Cow<'_, str> {
516 self.to_str()
517 }
518
519 fn to_buffer(&self) -> Result<Cow<'_, [u8]>, ParamValueParseError> {
520 self.to_buffer()
521 }
522
523 fn parse<T: FromStr>(&self) -> Result<T, T::Err> {
524 self.parse()
525 }
526
527 fn as_bytes(&self) -> Cow<'_, [u8]> {
528 match self {
529 Self::String(v) => Cow::Borrowed(v.as_bytes()),
530 Self::Buffer(v) => Cow::Borrowed(v.as_ref()),
531 Self::Float(v) => Cow::Owned(v.to_string().into_bytes()),
532 Self::Int(v) => Cow::Owned(v.to_string().into_bytes()),
533 Self::Empty => Cow::Borrowed(b""),
534 Self::Boolean(v) => Cow::Owned(v.to_string().into_bytes()),
535 Self::List(_) => Cow::Owned(self.to_string().into_bytes()),
536 }
537 }
538
539 fn as_ref(&self) -> ValueRef<'_> {
540 self.into()
541 }
542
543 fn data_len(&self) -> usize {
544 match self {
545 Self::String(v) => v.len(),
546 Self::Buffer(v) => v.len(),
547 Self::Float(_) => 8,
548 Self::Int(_) => 8,
549 Self::Empty => 0,
550 Self::Boolean(_) => mem::size_of::<bool>(),
551 Self::List(v) => v.iter().map(|vi| vi.data_len()).sum(),
552 }
553 }
554
555 fn is_boolean(&self) -> bool {
556 matches!(self, Self::Boolean(_))
557 }
558
559 fn to_bool(&self) -> Result<bool, ParamValueParseError> {
560 self.to_bool()
561 }
562
563 fn is_list(&self) -> bool {
564 self.is_list()
565 }
566
567 fn as_slice(&self) -> Cow<'_, [Value]> {
568 Cow::Borrowed(self.as_slice())
569 }
570}
571
572impl<U: Into<Value>> FromIterator<U> for Value {
573 fn from_iter<T: IntoIterator<Item = U>>(iter: T) -> Self {
574 let values: Box<[Value]> = iter.into_iter().map(|v| v.into()).collect();
575 Self::List(values)
576 }
577}
578
579impl From<Box<[Value]>> for Value {
580 fn from(value: Box<[Value]>) -> Self {
581 Self::List(value)
582 }
583}
584
585impl From<Vec<Value>> for Value {
586 fn from(value: Vec<Value>) -> Self {
587 Self::List(value.into_boxed_slice())
588 }
589}
590
591impl PartialEq<String> for Value {
592 fn eq(&self, other: &String) -> bool {
593 self.as_str() == other.as_str()
594 }
595}
596
597impl PartialEq<str> for Value {
598 fn eq(&self, other: &str) -> bool {
599 self.as_str() == other
600 }
601}
602
603impl PartialEq<&str> for Value {
604 fn eq(&self, other: &&str) -> bool {
605 self.as_str() == *other
606 }
607}
608
609impl PartialEq<i64> for Value {
610 fn eq(&self, other: &i64) -> bool {
611 if let Self::Int(val) = self {
612 val == other
613 } else {
614 false
615 }
616 }
617}
618
619impl PartialEq<f64> for Value {
620 fn eq(&self, other: &f64) -> bool {
621 if let Self::Float(val) = self {
622 val == other
623 } else {
624 false
625 }
626 }
627}
628
629impl PartialEq<bool> for Value {
630 fn eq(&self, other: &bool) -> bool {
631 if let Self::Boolean(val) = self {
632 val == other
633 } else {
634 false
635 }
636 }
637}
638
639impl Hash for Value {
640 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
641 core::mem::discriminant(self).hash(state);
642 match self {
643 Self::String(s) => s.hash(state),
644 Self::Float(v) => v.to_bits().hash(state),
645 Self::Int(v) => (*v).hash(state),
646 Self::Buffer(v) => v.hash(state),
647 Self::Empty => 0u8.hash(state),
648 Self::Boolean(v) => v.hash(state),
649 Self::List(v) => {
650 v.iter().for_each(|vi| vi.hash(state));
651 }
652 }
653 }
654}
655
656param_value_int!(i8);
657param_value_int!(i16);
658param_value_int!(i32);
659param_value_int!(i64);
660
661param_value_int!(u8);
662param_value_int!(u16);
663param_value_int!(u32);
664param_value_int!(u64);
665param_value_int!(usize);
666
667param_value_float!(f32);
668param_value_float!(f64);
669
670
671#[cfg(feature = "serde")]
674impl From<Value> for serde_json::Value {
675 fn from(value: Value) -> Self {
676 match value {
677 Value::Boolean(val) => serde_json::Value::Bool(val),
678 Value::Float(val) => {
679 serde_json::Value::Number(serde_json::Number::from_f64(val).unwrap())
680 }
681 Value::Int(val) => {
682 serde_json::Value::Number(serde_json::Number::from_i128(val as i128).unwrap())
683 }
684 Value::String(val) => serde_json::Value::String(val),
685 Value::Buffer(val) => serde_json::to_value(&val).unwrap(),
686 Value::Empty => serde_json::Value::Null,
687 Value::List(val) => {
688 let mut ve = Vec::new();
689 for vi in val {
690 ve.push(vi.into());
691 }
692 serde_json::Value::Array(ve)
693 }
694 }
695 }
696}