1use core::fmt;
9
10#[cfg_attr(all(feature = "std"), doc = "```")]
39#[cfg_attr(not(all(feature = "std")), doc = "```ignore")]
40#[derive(Clone, Copy, Default)]
55#[non_exhaustive]
56pub enum Value<'a> {
57 #[default]
59 Null,
60 Bool(bool),
62 I64(i64),
64 U64(u64),
66 I128(i128),
69 U128(u128),
72 F64(f64),
78 Str(&'a str),
80 Char(char),
82 Bytes(&'a [u8]),
84 Display(&'a dyn fmt::Display),
87 Debug(&'a dyn fmt::Debug),
90 Error(&'a (dyn core::error::Error + 'static)),
95}
96
97impl Value<'_> {
98 #[must_use]
108 pub const fn is_null(&self) -> bool {
109 matches!(self, Self::Null)
110 }
111
112 #[must_use]
122 pub const fn variant_name(&self) -> &'static str {
123 match self {
124 Self::Null => "null",
125 Self::Bool(_) => "bool",
126 Self::I64(_) => "i64",
127 Self::U64(_) => "u64",
128 Self::I128(_) => "i128",
129 Self::U128(_) => "u128",
130 Self::F64(_) => "f64",
131 Self::Str(_) => "str",
132 Self::Char(_) => "char",
133 Self::Bytes(_) => "bytes",
134 Self::Display(_) => "display",
135 Self::Debug(_) => "debug",
136 Self::Error(_) => "error",
137 }
138 }
139}
140
141pub(crate) fn write_error_chain<W: fmt::Write + ?Sized>(
143 w: &mut W,
144 err: &(dyn core::error::Error + 'static),
145) -> fmt::Result {
146 write!(w, "{err}")?;
147 let mut source = err.source();
148 while let Some(s) = source {
149 write!(w, ": {s}")?;
150 source = s.source();
151 }
152 Ok(())
153}
154
155pub(crate) fn write_hex<W: fmt::Write + ?Sized>(w: &mut W, bytes: &[u8]) -> fmt::Result {
157 const DIGITS: &[u8; 16] = b"0123456789abcdef";
158 for &b in bytes {
159 w.write_char(char::from(DIGITS[usize::from(b >> 4)]))?;
160 w.write_char(char::from(DIGITS[usize::from(b & 0x0f)]))?;
161 }
162 Ok(())
163}
164
165pub(crate) fn write_f64<W: fmt::Write + ?Sized>(w: &mut W, n: f64) -> fmt::Result {
169 if n.is_finite() {
170 write!(w, "{n:?}")
171 } else if n.is_nan() {
172 w.write_str("NaN")
173 } else if n.is_sign_positive() {
174 w.write_str("inf")
175 } else {
176 w.write_str("-inf")
177 }
178}
179
180impl fmt::Display for Value<'_> {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 match *self {
186 Self::Null => f.write_str("null"),
187 Self::Bool(b) => fmt::Display::fmt(&b, f),
188 Self::I64(n) => fmt::Display::fmt(&n, f),
189 Self::U64(n) => fmt::Display::fmt(&n, f),
190 Self::I128(n) => fmt::Display::fmt(&n, f),
191 Self::U128(n) => fmt::Display::fmt(&n, f),
192 Self::F64(n) => write_f64(f, n),
193 Self::Str(s) => f.write_str(s),
194 Self::Char(c) => fmt::Display::fmt(&c, f),
195 Self::Bytes(b) => write_hex(f, b),
196 Self::Display(d) => fmt::Display::fmt(d, f),
197 Self::Debug(d) => fmt::Debug::fmt(d, f),
198 Self::Error(e) => write_error_chain(f, e),
199 }
200 }
201}
202
203impl fmt::Debug for Value<'_> {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 match *self {
206 Self::Null => f.write_str("Null"),
207 Self::Bool(b) => f.debug_tuple("Bool").field(&b).finish(),
208 Self::I64(n) => f.debug_tuple("I64").field(&n).finish(),
209 Self::U64(n) => f.debug_tuple("U64").field(&n).finish(),
210 Self::I128(n) => f.debug_tuple("I128").field(&n).finish(),
211 Self::U128(n) => f.debug_tuple("U128").field(&n).finish(),
212 Self::F64(n) => f.debug_tuple("F64").field(&n).finish(),
213 Self::Str(s) => f.debug_tuple("Str").field(&s).finish(),
214 Self::Char(c) => f.debug_tuple("Char").field(&c).finish(),
215 Self::Bytes(b) => f.debug_tuple("Bytes").field(&b).finish(),
216 Self::Display(d) => f
217 .debug_tuple("Display")
218 .field(&format_args!("{d}"))
219 .finish(),
220 Self::Debug(d) => f.debug_tuple("Debug").field(&d).finish(),
221 Self::Error(e) => f.debug_tuple("Error").field(&format_args!("{e}")).finish(),
222 }
223 }
224}
225
226impl PartialEq for Value<'_> {
227 fn eq(&self, other: &Self) -> bool {
233 match (*self, *other) {
234 (Self::Null, Self::Null) => true,
235 (Self::Bool(a), Self::Bool(b)) => a == b,
236 (Self::I64(a), Self::I64(b)) => a == b,
237 (Self::U64(a), Self::U64(b)) => a == b,
238 (Self::I128(a), Self::I128(b)) => a == b,
239 (Self::U128(a), Self::U128(b)) => a == b,
240 (Self::F64(a), Self::F64(b)) => a == b,
241 (Self::Str(a), Self::Str(b)) => a == b,
242 (Self::Char(a), Self::Char(b)) => a == b,
243 (Self::Bytes(a), Self::Bytes(b)) => a == b,
244 (Self::Display(a), Self::Display(b)) => core::ptr::addr_eq(a, b),
245 (Self::Debug(a), Self::Debug(b)) => core::ptr::addr_eq(a, b),
246 (Self::Error(a), Self::Error(b)) => core::ptr::addr_eq(a, b),
247 _ => false,
248 }
249 }
250}
251
252impl<'a> From<&'a str> for Value<'a> {
256 fn from(value: &'a str) -> Self {
257 Self::Str(value)
258 }
259}
260
261impl<'a> From<&'a [u8]> for Value<'a> {
262 fn from(value: &'a [u8]) -> Self {
263 Self::Bytes(value)
264 }
265}
266
267impl From<bool> for Value<'_> {
268 fn from(value: bool) -> Self {
269 Self::Bool(value)
270 }
271}
272
273impl From<char> for Value<'_> {
274 fn from(value: char) -> Self {
275 Self::Char(value)
276 }
277}
278
279macro_rules! from_lossless_int {
280 ($($ty:ty => $variant:ident),* $(,)?) => {
281 $(
282 impl From<$ty> for Value<'_> {
283 fn from(value: $ty) -> Self {
284 Self::$variant(value.into())
285 }
286 }
287 )*
288 };
289}
290
291from_lossless_int!(
292 i8 => I64, i16 => I64, i32 => I64, i64 => I64,
293 u8 => U64, u16 => U64, u32 => U64, u64 => U64,
294 i128 => I128, u128 => U128,
295);
296
297impl From<isize> for Value<'_> {
298 fn from(value: isize) -> Self {
299 i64::try_from(value).map_or(Self::I128(value as i128), Self::I64)
302 }
303}
304
305impl From<usize> for Value<'_> {
306 fn from(value: usize) -> Self {
307 u64::try_from(value).map_or(Self::U128(value as u128), Self::U64)
308 }
309}
310
311impl From<f32> for Value<'_> {
312 fn from(value: f32) -> Self {
313 Self::F64(f64::from(value))
314 }
315}
316
317impl From<f64> for Value<'_> {
318 fn from(value: f64) -> Self {
319 Self::F64(value)
320 }
321}
322
323impl<'a, T> From<Option<T>> for Value<'a>
324where
325 T: Into<Value<'a>>,
326{
327 fn from(value: Option<T>) -> Self {
328 match value {
329 Some(v) => v.into(),
330 None => Self::Null,
331 }
332 }
333}
334
335#[cfg(feature = "std")]
336impl<'a> From<&'a String> for Value<'a> {
337 fn from(value: &'a String) -> Self {
338 Self::Str(value.as_str())
339 }
340}
341
342#[cfg(feature = "std")]
343impl<'a> From<&'a std::borrow::Cow<'a, str>> for Value<'a> {
344 fn from(value: &'a std::borrow::Cow<'a, str>) -> Self {
345 Self::Str(value.as_ref())
346 }
347}
348
349#[cfg(feature = "std")]
350impl<'a> From<&'a Vec<u8>> for Value<'a> {
351 fn from(value: &'a Vec<u8>) -> Self {
352 Self::Bytes(value.as_slice())
353 }
354}
355
356#[cfg(feature = "std")]
361#[derive(Debug, Clone, PartialEq)]
362pub(crate) enum OwnedValue {
363 Null,
364 Bool(bool),
365 I64(i64),
366 U64(u64),
367 I128(i128),
368 U128(u128),
369 F64(f64),
370 Str(Box<str>),
371 Char(char),
372 Bytes(Box<[u8]>),
373}
374
375#[cfg(feature = "std")]
376impl OwnedValue {
377 pub(crate) fn from_value(v: Value<'_>) -> Self {
378 match v {
379 Value::Null => Self::Null,
380 Value::Bool(b) => Self::Bool(b),
381 Value::I64(n) => Self::I64(n),
382 Value::U64(n) => Self::U64(n),
383 Value::I128(n) => Self::I128(n),
384 Value::U128(n) => Self::U128(n),
385 Value::F64(n) => Self::F64(n),
386 Value::Str(s) => Self::Str(s.into()),
387 Value::Char(c) => Self::Char(c),
388 Value::Bytes(b) => Self::Bytes(b.into()),
389 other @ (Value::Display(_) | Value::Debug(_) | Value::Error(_)) => {
390 Self::Str(other.to_string().into_boxed_str())
391 }
392 }
393 }
394
395 pub(crate) fn as_value(&self) -> Value<'_> {
396 match self {
397 Self::Null => Value::Null,
398 Self::Bool(b) => Value::Bool(*b),
399 Self::I64(n) => Value::I64(*n),
400 Self::U64(n) => Value::U64(*n),
401 Self::I128(n) => Value::I128(*n),
402 Self::U128(n) => Value::U128(*n),
403 Self::F64(n) => Value::F64(*n),
404 Self::Str(s) => Value::Str(s),
405 Self::Char(c) => Value::Char(*c),
406 Self::Bytes(b) => Value::Bytes(b),
407 }
408 }
409}
410
411#[cfg(feature = "std")]
413#[derive(Debug, Clone, PartialEq)]
414pub(crate) struct OwnedField {
415 pub(crate) key: Box<str>,
416 pub(crate) value: OwnedValue,
417}
418
419#[cfg(feature = "std")]
420impl OwnedField {
421 pub(crate) fn new(key: &str, value: Value<'_>) -> Self {
422 Self {
423 key: key.into(),
424 value: OwnedValue::from_value(value),
425 }
426 }
427
428 pub(crate) fn as_field(&self) -> crate::Field<'_> {
429 crate::Field {
430 key: &self.key,
431 value: self.value.as_value(),
432 }
433 }
434}
435
436#[cfg(all(test, feature = "std"))]
437mod tests {
438 use super::*;
439
440 #[derive(Debug)]
441 struct Outer(Inner);
442 #[derive(Debug)]
443 struct Inner;
444 impl fmt::Display for Outer {
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446 f.write_str("outer failed")
447 }
448 }
449 impl fmt::Display for Inner {
450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
451 f.write_str("inner cause")
452 }
453 }
454 impl core::error::Error for Outer {
455 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
456 Some(&self.0)
457 }
458 }
459 impl core::error::Error for Inner {}
460
461 #[test]
462 fn test_value_from_str_is_borrowed() {
463 let s = String::from("hello");
464 let v: Value<'_> = s.as_str().into();
465 assert_eq!(v, Value::Str("hello"));
466 let v: Value<'_> = (&s).into();
467 assert_eq!(v, Value::Str("hello"));
468 let c = std::borrow::Cow::Borrowed("cow");
469 assert_eq!(Value::from(&c), Value::Str("cow"));
470 let bytes = vec![1_u8, 2];
471 assert_eq!(Value::from(&bytes), Value::Bytes(&[1, 2]));
472 }
473
474 #[test]
475 fn test_value_integer_conversions_are_lossless() {
476 assert_eq!(Value::from(42_i32), Value::I64(42));
477 assert_eq!(Value::from(42_u32), Value::U64(42));
478 assert_eq!(Value::from(-1_i64), Value::I64(-1));
479 assert_eq!(Value::from(-1_isize), Value::I64(-1));
480 assert_eq!(Value::from(7_usize), Value::U64(7));
481 assert_eq!(Value::from(u128::MAX), Value::U128(u128::MAX));
482 assert_eq!(Value::from(i128::MIN), Value::I128(i128::MIN));
483 assert_eq!(Value::from(1.5_f32), Value::F64(1.5));
484 }
485
486 #[test]
487 fn test_value_option_none_is_null() {
488 let some: Value<'_> = Some(7_u32).into();
489 assert_eq!(some, Value::U64(7));
490 let none: Value<'_> = Option::<u32>::None.into();
491 assert!(none.is_null());
492 }
493
494 #[test]
495 fn test_value_variant_name_is_unique_per_variant() {
496 let e = Outer(Inner);
497 let names: Vec<&str> = [
498 Value::Null,
499 Value::Bool(true),
500 Value::I64(0),
501 Value::U64(0),
502 Value::I128(0),
503 Value::U128(0),
504 Value::F64(0.0),
505 Value::Str(""),
506 Value::Char('a'),
507 Value::Bytes(&[]),
508 Value::Display(&1),
509 Value::Debug(&1),
510 Value::Error(&e),
511 ]
512 .iter()
513 .map(Value::variant_name)
514 .collect();
515 let mut dedup = names.clone();
516 dedup.sort_unstable();
517 dedup.dedup();
518 assert_eq!(dedup.len(), names.len(), "variant names must be unique");
519 }
520
521 #[test]
522 fn test_value_display_renders_each_variant() {
523 let e = Outer(Inner);
524 assert_eq!(Value::Null.to_string(), "null");
525 assert_eq!(Value::Bool(true).to_string(), "true");
526 assert_eq!(Value::I64(-5).to_string(), "-5");
527 assert_eq!(Value::U64(5).to_string(), "5");
528 assert_eq!(Value::I128(-5).to_string(), "-5");
529 assert_eq!(Value::U128(5).to_string(), "5");
530 assert_eq!(Value::F64(1.0).to_string(), "1.0");
531 assert_eq!(Value::F64(f64::NAN).to_string(), "NaN");
532 assert_eq!(Value::F64(f64::INFINITY).to_string(), "inf");
533 assert_eq!(Value::F64(f64::NEG_INFINITY).to_string(), "-inf");
534 assert_eq!(Value::Str("x").to_string(), "x");
535 assert_eq!(Value::Char('y').to_string(), "y");
536 assert_eq!(Value::Bytes(&[0x00, 0xab, 0xff]).to_string(), "00abff");
537 assert_eq!(Value::Display(&42).to_string(), "42");
538 assert_eq!(Value::Debug(&"q").to_string(), "\"q\"");
539 assert_eq!(Value::Error(&e).to_string(), "outer failed: inner cause");
540 }
541
542 #[test]
543 fn test_value_debug_is_readable() {
544 assert_eq!(format!("{:?}", Value::U64(3)), "U64(3)");
545 assert_eq!(format!("{:?}", Value::Display(&7)), "Display(7)");
546 assert_eq!(format!("{:?}", Value::Debug(&7)), "Debug(7)");
547 assert_eq!(format!("{:?}", Value::Null), "Null");
548 let e = Outer(Inner);
549 assert_eq!(format!("{:?}", Value::Error(&e)), "Error(outer failed)");
550 }
551
552 #[test]
553 fn test_value_eq_lazy_variants_compare_by_identity() {
554 let a = 5;
555 let b = 5;
556 assert_eq!(Value::Display(&a), Value::Display(&a));
557 assert_ne!(Value::Display(&a), Value::Display(&b));
558 assert_eq!(Value::Debug(&a), Value::Debug(&a));
559 assert_ne!(Value::F64(f64::NAN), Value::F64(f64::NAN));
560 assert_ne!(Value::U64(1), Value::I64(1));
561 let e = Outer(Inner);
562 assert_eq!(Value::Error(&e), Value::Error(&e));
563 }
564
565 #[test]
566 fn test_owned_value_renders_lazy_variants_to_text() {
567 let e = Outer(Inner);
568 let owned = OwnedValue::from_value(Value::Error(&e));
569 assert_eq!(owned.as_value(), Value::Str("outer failed: inner cause"));
570 let owned = OwnedValue::from_value(Value::Bytes(&[1, 2]));
571 assert_eq!(owned.as_value(), Value::Bytes(&[1, 2]));
572 for v in [
573 Value::Null,
574 Value::Bool(true),
575 Value::I64(-1),
576 Value::U64(1),
577 Value::I128(-2),
578 Value::U128(2),
579 Value::F64(0.5),
580 Value::Str("s"),
581 Value::Char('c'),
582 ] {
583 assert_eq!(OwnedValue::from_value(v).as_value(), v);
584 }
585 }
586
587 #[test]
588 fn test_float_text_is_round_trippable() {
589 for x in [1.0, 0.1, 1e300, f64::MAX, 5e-324, -0.0, 1e21, 1e-7] {
590 let s = Value::F64(x).to_string();
591 assert!(s.contains('.') || s.contains('e'), "{s}");
592 assert_eq!(s.parse::<f64>().unwrap().to_bits(), x.to_bits(), "{s}");
593 }
594 }
595}