1 //! Structured values. 2 3 use std::fmt; 4 5 extern crate value_bag; 6 7 #[cfg(feature = "kv_unstable_sval")] 8 extern crate sval; 9 10 #[cfg(feature = "kv_unstable_serde")] 11 extern crate serde; 12 13 use self::value_bag::ValueBag; 14 15 pub use kv::Error; 16 17 /// A type that can be converted into a [`Value`](struct.Value.html). 18 pub trait ToValue { 19 /// Perform the conversion. to_value(&self) -> Value20 fn to_value(&self) -> Value; 21 } 22 23 impl<'a, T> ToValue for &'a T 24 where 25 T: ToValue + ?Sized, 26 { to_value(&self) -> Value27 fn to_value(&self) -> Value { 28 (**self).to_value() 29 } 30 } 31 32 impl<'v> ToValue for Value<'v> { to_value(&self) -> Value33 fn to_value(&self) -> Value { 34 Value { 35 inner: self.inner.clone(), 36 } 37 } 38 } 39 40 /// A value in a structured key-value pair. 41 /// 42 /// # Capturing values 43 /// 44 /// There are a few ways to capture a value: 45 /// 46 /// - Using the `Value::capture_*` methods. 47 /// - Using the `Value::from_*` methods. 48 /// - Using the `ToValue` trait. 49 /// - Using the standard `From` trait. 50 /// 51 /// ## Using the `Value::capture_*` methods 52 /// 53 /// `Value` offers a few constructor methods that capture values of different kinds. 54 /// These methods require a `T: 'static` to support downcasting. 55 /// 56 /// ``` 57 /// use log::kv::Value; 58 /// 59 /// let value = Value::capture_debug(&42i32); 60 /// 61 /// assert_eq!(Some(42), value.to_i64()); 62 /// ``` 63 /// 64 /// ## Using the `Value::from_*` methods 65 /// 66 /// `Value` offers a few constructor methods that capture values of different kinds. 67 /// These methods don't require `T: 'static`, but can't support downcasting. 68 /// 69 /// ``` 70 /// use log::kv::Value; 71 /// 72 /// let value = Value::from_debug(&42i32); 73 /// 74 /// assert_eq!(None, value.to_i64()); 75 /// ``` 76 /// 77 /// ## Using the `ToValue` trait 78 /// 79 /// The `ToValue` trait can be used to capture values generically. 80 /// It's the bound used by `Source`. 81 /// 82 /// ``` 83 /// # use log::kv::ToValue; 84 /// let value = 42i32.to_value(); 85 /// 86 /// assert_eq!(Some(42), value.to_i64()); 87 /// ``` 88 /// 89 /// ``` 90 /// # use std::fmt::Debug; 91 /// use log::kv::ToValue; 92 /// 93 /// let value = (&42i32 as &dyn Debug).to_value(); 94 /// 95 /// assert_eq!(None, value.to_i64()); 96 /// ``` 97 /// 98 /// ## Using the standard `From` trait 99 /// 100 /// Standard types that implement `ToValue` also implement `From`. 101 /// 102 /// ``` 103 /// use log::kv::Value; 104 /// 105 /// let value = Value::from(42i32); 106 /// 107 /// assert_eq!(Some(42), value.to_i64()); 108 /// ``` 109 pub struct Value<'v> { 110 inner: ValueBag<'v>, 111 } 112 113 impl<'v> Value<'v> { 114 /// Get a value from a type implementing `ToValue`. from_any<T>(value: &'v T) -> Self where T: ToValue,115 pub fn from_any<T>(value: &'v T) -> Self 116 where 117 T: ToValue, 118 { 119 value.to_value() 120 } 121 122 /// Get a value from a type implementing `std::fmt::Debug`. capture_debug<T>(value: &'v T) -> Self where T: fmt::Debug + 'static,123 pub fn capture_debug<T>(value: &'v T) -> Self 124 where 125 T: fmt::Debug + 'static, 126 { 127 Value { 128 inner: ValueBag::capture_debug(value), 129 } 130 } 131 132 /// Get a value from a type implementing `std::fmt::Display`. capture_display<T>(value: &'v T) -> Self where T: fmt::Display + 'static,133 pub fn capture_display<T>(value: &'v T) -> Self 134 where 135 T: fmt::Display + 'static, 136 { 137 Value { 138 inner: ValueBag::capture_display(value), 139 } 140 } 141 142 /// Get a value from an error. 143 #[cfg(feature = "kv_unstable_std")] capture_error<T>(err: &'v T) -> Self where T: std::error::Error + 'static,144 pub fn capture_error<T>(err: &'v T) -> Self 145 where 146 T: std::error::Error + 'static, 147 { 148 Value { 149 inner: ValueBag::capture_error(err), 150 } 151 } 152 153 #[cfg(feature = "kv_unstable_serde")] 154 /// Get a value from a type implementing `serde::Serialize`. capture_serde<T>(value: &'v T) -> Self where T: self::serde::Serialize + 'static,155 pub fn capture_serde<T>(value: &'v T) -> Self 156 where 157 T: self::serde::Serialize + 'static, 158 { 159 Value { 160 inner: ValueBag::capture_serde1(value), 161 } 162 } 163 164 /// Get a value from a type implementing `sval::value::Value`. 165 #[cfg(feature = "kv_unstable_sval")] capture_sval<T>(value: &'v T) -> Self where T: self::sval::value::Value + 'static,166 pub fn capture_sval<T>(value: &'v T) -> Self 167 where 168 T: self::sval::value::Value + 'static, 169 { 170 Value { 171 inner: ValueBag::capture_sval1(value), 172 } 173 } 174 175 /// Get a value from a type implementing `std::fmt::Debug`. from_debug<T>(value: &'v T) -> Self where T: fmt::Debug,176 pub fn from_debug<T>(value: &'v T) -> Self 177 where 178 T: fmt::Debug, 179 { 180 Value { 181 inner: ValueBag::from_debug(value), 182 } 183 } 184 185 /// Get a value from a type implementing `std::fmt::Display`. from_display<T>(value: &'v T) -> Self where T: fmt::Display,186 pub fn from_display<T>(value: &'v T) -> Self 187 where 188 T: fmt::Display, 189 { 190 Value { 191 inner: ValueBag::from_display(value), 192 } 193 } 194 195 /// Get a value from a type implementing `serde::Serialize`. 196 #[cfg(feature = "kv_unstable_serde")] from_serde<T>(value: &'v T) -> Self where T: self::serde::Serialize,197 pub fn from_serde<T>(value: &'v T) -> Self 198 where 199 T: self::serde::Serialize, 200 { 201 Value { 202 inner: ValueBag::from_serde1(value), 203 } 204 } 205 206 /// Get a value from a type implementing `sval::value::Value`. 207 #[cfg(feature = "kv_unstable_sval")] from_sval<T>(value: &'v T) -> Self where T: self::sval::value::Value,208 pub fn from_sval<T>(value: &'v T) -> Self 209 where 210 T: self::sval::value::Value, 211 { 212 Value { 213 inner: ValueBag::from_sval1(value), 214 } 215 } 216 217 /// Get a value from a dynamic `std::fmt::Debug`. from_dyn_debug(value: &'v dyn fmt::Debug) -> Self218 pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self { 219 Value { 220 inner: ValueBag::from_dyn_debug(value), 221 } 222 } 223 224 /// Get a value from a dynamic `std::fmt::Display`. from_dyn_display(value: &'v dyn fmt::Display) -> Self225 pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self { 226 Value { 227 inner: ValueBag::from_dyn_display(value), 228 } 229 } 230 231 /// Get a value from a dynamic error. 232 #[cfg(feature = "kv_unstable_std")] from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self233 pub fn from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self { 234 Value { 235 inner: ValueBag::from_dyn_error(err), 236 } 237 } 238 239 /// Get a value from a type implementing `sval::value::Value`. 240 #[cfg(feature = "kv_unstable_sval")] from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self241 pub fn from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self { 242 Value { 243 inner: ValueBag::from_dyn_sval1(value), 244 } 245 } 246 247 /// Get a value from an internal primitive. from_value_bag<T>(value: T) -> Self where T: Into<ValueBag<'v>>,248 fn from_value_bag<T>(value: T) -> Self 249 where 250 T: Into<ValueBag<'v>>, 251 { 252 Value { 253 inner: value.into(), 254 } 255 } 256 257 /// Check whether this value can be downcast to `T`. is<T: 'static>(&self) -> bool258 pub fn is<T: 'static>(&self) -> bool { 259 self.inner.is::<T>() 260 } 261 262 /// Try downcast this value to `T`. downcast_ref<T: 'static>(&self) -> Option<&T>263 pub fn downcast_ref<T: 'static>(&self) -> Option<&T> { 264 self.inner.downcast_ref::<T>() 265 } 266 } 267 268 impl<'v> fmt::Debug for Value<'v> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 270 fmt::Debug::fmt(&self.inner, f) 271 } 272 } 273 274 impl<'v> fmt::Display for Value<'v> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 276 fmt::Display::fmt(&self.inner, f) 277 } 278 } 279 280 impl ToValue for dyn fmt::Debug { to_value(&self) -> Value281 fn to_value(&self) -> Value { 282 Value::from_dyn_debug(self) 283 } 284 } 285 286 impl ToValue for dyn fmt::Display { to_value(&self) -> Value287 fn to_value(&self) -> Value { 288 Value::from_dyn_display(self) 289 } 290 } 291 292 #[cfg(feature = "kv_unstable_std")] 293 impl ToValue for dyn std::error::Error + 'static { to_value(&self) -> Value294 fn to_value(&self) -> Value { 295 Value::from_dyn_error(self) 296 } 297 } 298 299 #[cfg(feature = "kv_unstable_serde")] 300 impl<'v> self::serde::Serialize for Value<'v> { serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> where S: self::serde::Serializer,301 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error> 302 where 303 S: self::serde::Serializer, 304 { 305 self.inner.serialize(s) 306 } 307 } 308 309 #[cfg(feature = "kv_unstable_sval")] 310 impl<'v> self::sval::value::Value for Value<'v> { stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result311 fn stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result { 312 self::sval::value::Value::stream(&self.inner, stream) 313 } 314 } 315 316 #[cfg(feature = "kv_unstable_sval")] 317 impl ToValue for dyn self::sval::value::Value { to_value(&self) -> Value318 fn to_value(&self) -> Value { 319 Value::from_dyn_sval(self) 320 } 321 } 322 323 impl ToValue for str { to_value(&self) -> Value324 fn to_value(&self) -> Value { 325 Value::from(self) 326 } 327 } 328 329 impl<'v> From<&'v str> for Value<'v> { from(value: &'v str) -> Self330 fn from(value: &'v str) -> Self { 331 Value::from_value_bag(value) 332 } 333 } 334 335 impl ToValue for () { to_value(&self) -> Value336 fn to_value(&self) -> Value { 337 Value::from_value_bag(()) 338 } 339 } 340 341 impl<T> ToValue for Option<T> 342 where 343 T: ToValue, 344 { to_value(&self) -> Value345 fn to_value(&self) -> Value { 346 match *self { 347 Some(ref value) => value.to_value(), 348 None => Value::from_value_bag(()), 349 } 350 } 351 } 352 353 macro_rules! impl_to_value_primitive { 354 ($($into_ty:ty,)*) => { 355 $( 356 impl ToValue for $into_ty { 357 fn to_value(&self) -> Value { 358 Value::from(*self) 359 } 360 } 361 362 impl<'v> From<$into_ty> for Value<'v> { 363 fn from(value: $into_ty) -> Self { 364 Value::from_value_bag(value) 365 } 366 } 367 )* 368 }; 369 } 370 371 macro_rules! impl_value_to_primitive { 372 ($(#[doc = $doc:tt] $into_name:ident -> $into_ty:ty,)*) => { 373 impl<'v> Value<'v> { 374 $( 375 #[doc = $doc] 376 pub fn $into_name(&self) -> Option<$into_ty> { 377 self.inner.$into_name() 378 } 379 )* 380 } 381 } 382 } 383 384 impl_to_value_primitive![ 385 usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool, 386 ]; 387 388 impl_value_to_primitive![ 389 #[doc = "Try convert this value into a `u64`."] 390 to_u64 -> u64, 391 #[doc = "Try convert this value into a `i64`."] 392 to_i64 -> i64, 393 #[doc = "Try convert this value into a `u128`."] 394 to_u128 -> u128, 395 #[doc = "Try convert this value into a `i128`."] 396 to_i128 -> i128, 397 #[doc = "Try convert this value into a `f64`."] 398 to_f64 -> f64, 399 #[doc = "Try convert this value into a `char`."] 400 to_char -> char, 401 #[doc = "Try convert this value into a `bool`."] 402 to_bool -> bool, 403 ]; 404 405 impl<'v> Value<'v> { 406 /// Try convert this value into an error. 407 #[cfg(feature = "kv_unstable_std")] to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)>408 pub fn to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)> { 409 self.inner.to_borrowed_error() 410 } 411 412 /// Try convert this value into a borrowed string. to_borrowed_str(&self) -> Option<&str>413 pub fn to_borrowed_str(&self) -> Option<&str> { 414 self.inner.to_borrowed_str() 415 } 416 } 417 418 #[cfg(feature = "kv_unstable_std")] 419 mod std_support { 420 use super::*; 421 422 use std::borrow::Cow; 423 424 impl<T> ToValue for Box<T> 425 where 426 T: ToValue + ?Sized, 427 { to_value(&self) -> Value428 fn to_value(&self) -> Value { 429 (**self).to_value() 430 } 431 } 432 433 impl ToValue for String { to_value(&self) -> Value434 fn to_value(&self) -> Value { 435 Value::from(&**self) 436 } 437 } 438 439 impl<'v> ToValue for Cow<'v, str> { to_value(&self) -> Value440 fn to_value(&self) -> Value { 441 Value::from(&**self) 442 } 443 } 444 445 impl<'v> Value<'v> { 446 /// Try convert this value into a string. to_str(&self) -> Option<Cow<str>>447 pub fn to_str(&self) -> Option<Cow<str>> { 448 self.inner.to_str() 449 } 450 } 451 } 452 453 #[cfg(test)] 454 pub(crate) mod tests { 455 use super::*; 456 457 pub(crate) use super::value_bag::test::Token; 458 459 impl<'v> Value<'v> { to_token(&self) -> Token460 pub(crate) fn to_token(&self) -> Token { 461 self.inner.to_token() 462 } 463 } 464 unsigned() -> impl Iterator<Item = Value<'static>>465 fn unsigned() -> impl Iterator<Item = Value<'static>> { 466 vec![ 467 Value::from(8u8), 468 Value::from(16u16), 469 Value::from(32u32), 470 Value::from(64u64), 471 Value::from(1usize), 472 ] 473 .into_iter() 474 } 475 signed() -> impl Iterator<Item = Value<'static>>476 fn signed() -> impl Iterator<Item = Value<'static>> { 477 vec![ 478 Value::from(-8i8), 479 Value::from(-16i16), 480 Value::from(-32i32), 481 Value::from(-64i64), 482 Value::from(-1isize), 483 ] 484 .into_iter() 485 } 486 float() -> impl Iterator<Item = Value<'static>>487 fn float() -> impl Iterator<Item = Value<'static>> { 488 vec![Value::from(32.32f32), Value::from(64.64f64)].into_iter() 489 } 490 bool() -> impl Iterator<Item = Value<'static>>491 fn bool() -> impl Iterator<Item = Value<'static>> { 492 vec![Value::from(true), Value::from(false)].into_iter() 493 } 494 str() -> impl Iterator<Item = Value<'static>>495 fn str() -> impl Iterator<Item = Value<'static>> { 496 vec![Value::from("a string"), Value::from("a loong string")].into_iter() 497 } 498 char() -> impl Iterator<Item = Value<'static>>499 fn char() -> impl Iterator<Item = Value<'static>> { 500 vec![Value::from('a'), Value::from('⛰')].into_iter() 501 } 502 503 #[test] test_capture_fmt()504 fn test_capture_fmt() { 505 assert_eq!(Some(42u64), Value::capture_display(&42).to_u64()); 506 assert_eq!(Some(42u64), Value::capture_debug(&42).to_u64()); 507 508 assert!(Value::from_display(&42).to_u64().is_none()); 509 assert!(Value::from_debug(&42).to_u64().is_none()); 510 } 511 512 #[cfg(feature = "kv_unstable_std")] 513 #[test] test_capture_error()514 fn test_capture_error() { 515 let err = std::io::Error::from(std::io::ErrorKind::Other); 516 517 assert!(Value::capture_error(&err).to_borrowed_error().is_some()); 518 assert!(Value::from_dyn_error(&err).to_borrowed_error().is_some()); 519 } 520 521 #[cfg(feature = "kv_unstable_serde")] 522 #[test] test_capture_serde()523 fn test_capture_serde() { 524 assert_eq!(Some(42u64), Value::capture_serde(&42).to_u64()); 525 526 assert_eq!(Some(42u64), Value::from_serde(&42).to_u64()); 527 } 528 529 #[cfg(feature = "kv_unstable_sval")] 530 #[test] test_capture_sval()531 fn test_capture_sval() { 532 assert_eq!(Some(42u64), Value::capture_sval(&42).to_u64()); 533 534 assert_eq!(Some(42u64), Value::from_sval(&42).to_u64()); 535 } 536 537 #[test] test_to_value_display()538 fn test_to_value_display() { 539 assert_eq!(42u64.to_value().to_string(), "42"); 540 assert_eq!(42i64.to_value().to_string(), "42"); 541 assert_eq!(42.01f64.to_value().to_string(), "42.01"); 542 assert_eq!(true.to_value().to_string(), "true"); 543 assert_eq!('a'.to_value().to_string(), "a"); 544 assert_eq!("a loong string".to_value().to_string(), "a loong string"); 545 assert_eq!(Some(true).to_value().to_string(), "true"); 546 assert_eq!(().to_value().to_string(), "None"); 547 assert_eq!(Option::None::<bool>.to_value().to_string(), "None"); 548 } 549 550 #[test] test_to_value_structured()551 fn test_to_value_structured() { 552 assert_eq!(42u64.to_value().to_token(), Token::U64(42)); 553 assert_eq!(42i64.to_value().to_token(), Token::I64(42)); 554 assert_eq!(42.01f64.to_value().to_token(), Token::F64(42.01)); 555 assert_eq!(true.to_value().to_token(), Token::Bool(true)); 556 assert_eq!('a'.to_value().to_token(), Token::Char('a')); 557 assert_eq!( 558 "a loong string".to_value().to_token(), 559 Token::Str("a loong string".into()) 560 ); 561 assert_eq!(Some(true).to_value().to_token(), Token::Bool(true)); 562 assert_eq!(().to_value().to_token(), Token::None); 563 assert_eq!(Option::None::<bool>.to_value().to_token(), Token::None); 564 } 565 566 #[test] test_to_number()567 fn test_to_number() { 568 for v in unsigned() { 569 assert!(v.to_u64().is_some()); 570 assert!(v.to_i64().is_some()); 571 } 572 573 for v in signed() { 574 assert!(v.to_i64().is_some()); 575 } 576 577 for v in unsigned().chain(signed()).chain(float()) { 578 assert!(v.to_f64().is_some()); 579 } 580 581 for v in bool().chain(str()).chain(char()) { 582 assert!(v.to_u64().is_none()); 583 assert!(v.to_i64().is_none()); 584 assert!(v.to_f64().is_none()); 585 } 586 } 587 588 #[test] test_to_str()589 fn test_to_str() { 590 for v in str() { 591 assert!(v.to_borrowed_str().is_some()); 592 593 #[cfg(feature = "kv_unstable_std")] 594 assert!(v.to_str().is_some()); 595 } 596 597 let short_lived = String::from("short lived"); 598 let v = Value::from(&*short_lived); 599 600 assert!(v.to_borrowed_str().is_some()); 601 602 #[cfg(feature = "kv_unstable_std")] 603 assert!(v.to_str().is_some()); 604 605 for v in unsigned().chain(signed()).chain(float()).chain(bool()) { 606 assert!(v.to_borrowed_str().is_none()); 607 608 #[cfg(feature = "kv_unstable_std")] 609 assert!(v.to_str().is_none()); 610 } 611 } 612 613 #[test] test_to_bool()614 fn test_to_bool() { 615 for v in bool() { 616 assert!(v.to_bool().is_some()); 617 } 618 619 for v in unsigned() 620 .chain(signed()) 621 .chain(float()) 622 .chain(str()) 623 .chain(char()) 624 { 625 assert!(v.to_bool().is_none()); 626 } 627 } 628 629 #[test] test_to_char()630 fn test_to_char() { 631 for v in char() { 632 assert!(v.to_char().is_some()); 633 } 634 635 for v in unsigned() 636 .chain(signed()) 637 .chain(float()) 638 .chain(str()) 639 .chain(bool()) 640 { 641 assert!(v.to_char().is_none()); 642 } 643 } 644 645 #[test] test_downcast_ref()646 fn test_downcast_ref() { 647 #[derive(Debug)] 648 struct Foo(u64); 649 650 let v = Value::capture_debug(&Foo(42)); 651 652 assert!(v.is::<Foo>()); 653 assert_eq!(42u64, v.downcast_ref::<Foo>().expect("invalid downcast").0); 654 } 655 } 656