Struct value_bag::ValueBag [−][src]
A dynamic structured value.
Capturing values
There are a few ways to capture a value:
- Using the
ValueBag::capture_*
andValueBag::from_*
methods. - Using the standard
From
trait. - Using the
Fill
API.
Using the ValueBag::capture_*
methods
ValueBag
offers a few constructor methods that capture values of different kinds.
These methods require a T: 'static
to support downcasting.
use value_bag::ValueBag; let value = ValueBag::capture_debug(&42i32); assert_eq!(Some(42), value.to_i64());
Capturing a value using these methods will retain type information so that the contents of the bag can be serialized using an appropriate type.
For cases where the 'static
bound can’t be satisfied, there’s also a few
constructors that exclude it.
use value_bag::ValueBag; let value = ValueBag::from_debug(&42i32); assert_eq!(None, value.to_i64());
These ValueBag::from_*
methods are lossy though and ValueBag::capture_*
should be preferred.
Using the standard From
trait
Primitive types can be converted into a ValueBag
using the standard From
trait.
use value_bag::ValueBag; let value = ValueBag::from(42i32); assert_eq!(Some(42), value.to_i64());
Using the Fill
API
The fill
module provides a way to bridge APIs that may not be directly
compatible with other constructor methods.
The Fill
trait is automatically implemented for closures, so can usually
be used in libraries that can’t implement the trait themselves.
use value_bag::{ValueBag, fill::Slot}; let value = ValueBag::from_fill(&|slot: &mut Slot| { #[derive(Debug)] struct MyShortLivedValue; slot.fill_debug(&MyShortLivedValue) }); assert_eq!("MyShortLivedValue", format!("{:?}", value));
The trait can also be implemented manually:
use value_bag::{ValueBag, Error, fill::{Slot, Fill}}; struct FillDebug; impl Fill for FillDebug { fn fill(&self, slot: &mut Slot) -> Result<(), Error> { slot.fill_debug(&42i32 as &dyn Debug) } } let value = ValueBag::from_fill(&FillDebug); assert_eq!(None, value.to_i64());
Inspecting values
Once you have a ValueBag
there are also a few ways to inspect it:
- Using
std::fmt
- Using
sval
- Using
serde
- Using the
ValueBag::visit
method. - Using the
ValueBag::to_*
methods. - Using the
ValueBag::downcast_ref
method.
Using the ValueBag::visit
method
The visit
module provides a simple visitor API that can be used to inspect
the structure of primitives stored in a ValueBag
.
More complex datatypes can then be handled using std::fmt
, sval
, or serde
.
#[cfg(not(feature = "std"))] fn main() {} #[cfg(feature = "std")] use value_bag::{ValueBag, Error, visit::Visit}; // Implement some simple custom serialization struct MyVisit(Vec<u8>); impl<'v> Visit<'v> for MyVisit { fn visit_any(&mut self, v: ValueBag) -> Result<(), Error> { // Fallback to `Debug` if we didn't visit the value specially write!(&mut self.0, "{:?}", v).map_err(|_| Error::msg("failed to write value")) } fn visit_u64(&mut self, v: u64) -> Result<(), Error> { self.0.extend_from_slice(itoa_fmt(v).as_slice()); Ok(()) } fn visit_i64(&mut self, v: i64) -> Result<(), Error> { self.0.extend_from_slice(itoa_fmt(v).as_slice()); Ok(()) } fn visit_f64(&mut self, v: f64) -> Result<(), Error> { self.0.extend_from_slice(ryu_fmt(v).as_slice()); Ok(()) } fn visit_str(&mut self, v: &str) -> Result<(), Error> { self.0.push(b'\"'); self.0.extend_from_slice(escape(v.as_bytes())); self.0.push(b'\"'); Ok(()) } fn visit_bool(&mut self, v: bool) -> Result<(), Error> { self.0.extend_from_slice(if v { b"true" } else { b"false" }); Ok(()) } } let value = ValueBag::from(42i64); let mut visitor = MyVisit(vec![]); value.visit(&mut visitor)?;
Using std::fmt
Any ValueBag
can be formatted using the std::fmt
machinery as either Debug
or Display
.
use value_bag::ValueBag; let value = ValueBag::from(true); assert_eq!("true", format!("{:?}", value));
Using sval
When the sval1
feature is enabled, any ValueBag
can be serialized using sval
.
This makes it possible to visit any typed structure captured in the ValueBag
,
including complex datatypes like maps and sequences.
sval
doesn’t need to allocate so can be used in no-std environments.
First, enable the sval1
feature in your Cargo.toml
:
[dependencies.value-bag]
features = ["sval1"]
Then stream the contents of the ValueBag
using sval
.
#[cfg(not(all(feature = "std", feature = "sval1")))] fn main() {} #[cfg(all(feature = "std", feature = "sval1"))] use value_bag::ValueBag; let value = ValueBag::from(42i64); let json = sval_json::to_string(value)?;
#[cfg(not(all(feature = "std", feature = "sval1")))] fn main() {} #[cfg(all(feature = "std", feature = "sval1"))] use value_bag::ValueBag; use sval::stream::{self, Stream}; // Implement some simple custom serialization struct MyStream(Vec<u8>); impl Stream for MyStream { fn u64(&mut self, v: u64) -> stream::Result { self.0.extend_from_slice(itoa_fmt(v).as_slice()); Ok(()) } fn i64(&mut self, v: i64) -> stream::Result { self.0.extend_from_slice(itoa_fmt(v).as_slice()); Ok(()) } fn f64(&mut self, v: f64) -> stream::Result { self.0.extend_from_slice(ryu_fmt(v).as_slice()); Ok(()) } fn str(&mut self, v: &str) -> stream::Result { self.0.push(b'\"'); self.0.extend_from_slice(escape(v.as_bytes())); self.0.push(b'\"'); Ok(()) } fn bool(&mut self, v: bool) -> stream::Result { self.0.extend_from_slice(if v { b"true" } else { b"false" }); Ok(()) } } let value = ValueBag::from(42i64); let mut stream = MyStream(vec![]); sval::stream(&mut stream, &value)?;
Using serde
When the serde1
feature is enabled, any ValueBag
can be serialized using serde
.
This makes it possible to visit any typed structure captured in the ValueBag
,
including complex datatypes like maps and sequences.
serde
needs a few temporary allocations, so also brings in the std
feature.
First, enable the serde1
feature in your Cargo.toml
:
[dependencies.value-bag]
features = ["serde1"]
Then stream the contents of the ValueBag
using serde
.
#[cfg(not(all(feature = "std", feature = "serde1")))] fn main() {} #[cfg(all(feature = "std", feature = "serde1"))] use value_bag::ValueBag; let value = ValueBag::from(42i64); let json = serde_json::to_string(&value)?;
Also see serde.rs
for more examples of writing your own serializers.
Using the ValueBag::to_*
methods
ValueBag
provides a set of methods for attempting to pull a concrete value out.
These are useful for ad-hoc analysis but aren’t intended for exhaustively serializing
the contents of a ValueBag
.
use value_bag::ValueBag; let value = ValueBag::capture_display(&42u64); assert_eq!(Some(42u64), value.to_u64());
Using the ValueBag::downcast_ref
method
When a ValueBag
is created using one of the capture_*
constructors, it can be downcast
back to its original value.
This can also be useful for ad-hoc analysis where there’s a common possible non-primitive
type that could be captured.
use value_bag::ValueBag; let timestamp = now(); let value = ValueBag::capture_debug(×tamp); assert!(value.downcast_ref::<SystemTime>().is_some());
Implementations
impl<'v> ValueBag<'v>
[src]
impl<'v> ValueBag<'v>
[src]
pub fn to_u64(&self) -> Option<u64>
[src]
Try get a u64
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
pub fn to_i64(&self) -> Option<i64>
[src]
Try get a i64
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
pub fn to_u128(&self) -> Option<u128>
[src]
Try get a u128
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
pub fn to_i128(&self) -> Option<i128>
[src]
Try get a i128
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
pub fn to_f64(&self) -> Option<f64>
[src]
Try get a f64
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
pub fn to_bool(&self) -> Option<bool>
[src]
Try get a bool
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
pub fn to_char(&self) -> Option<char>
[src]
Try get a char
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
pub fn to_borrowed_str(&self) -> Option<&str>
[src]
Try get a str
from this value.
This method is cheap for primitive types. It won’t allocate an owned
String
if the value is a complex type.
pub fn is<T: 'static>(&self) -> bool
[src]
Check whether this value can be downcast to T
.
pub fn downcast_ref<T: 'static>(&self) -> Option<&T>
[src]
Try downcast this value to T
.
impl<'v> ValueBag<'v>
[src]
pub fn capture_debug<T>(value: &'v T) -> Self where
T: Debug + 'static,
[src]
T: Debug + 'static,
Get a value from a debuggable type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Debug
implementation.
pub fn capture_display<T>(value: &'v T) -> Self where
T: Display + 'static,
[src]
T: Display + 'static,
Get a value from a displayable type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Display
implementation.
pub fn from_debug<T>(value: &'v T) -> Self where
T: Debug,
[src]
T: Debug,
Get a value from a debuggable type without capturing support.
pub fn from_display<T>(value: &'v T) -> Self where
T: Display,
[src]
T: Display,
Get a value from a displayable type without capturing support.
pub fn from_dyn_debug(value: &'v dyn Debug) -> Self
[src]
Get a value from a debuggable type without capturing support.
pub fn from_dyn_display(value: &'v dyn Display) -> Self
[src]
Get a value from a displayable type without capturing support.
impl<'v> ValueBag<'v>
[src]
Trait Implementations
impl<'v> Clone for ValueBag<'v>
[src]
fn clone(&self) -> ValueBag<'v>
[src]
pub fn clone_from(&mut self, source: &Self)
1.0.0[src]
impl<'v> Debug for ValueBag<'v>
[src]
impl<'v> Display for ValueBag<'v>
[src]
impl<'v> From<&'v str> for ValueBag<'v>
[src]
impl<'v> From<()> for ValueBag<'v>
[src]
impl<'v> From<bool> for ValueBag<'v>
[src]
impl<'v> From<char> for ValueBag<'v>
[src]
impl<'v> From<f32> for ValueBag<'v>
[src]
impl<'v> From<f64> for ValueBag<'v>
[src]
impl<'v> From<i128> for ValueBag<'v>
[src]
impl<'v> From<i16> for ValueBag<'v>
[src]
impl<'v> From<i32> for ValueBag<'v>
[src]
impl<'v> From<i64> for ValueBag<'v>
[src]
impl<'v> From<i8> for ValueBag<'v>
[src]
impl<'v> From<isize> for ValueBag<'v>
[src]
impl<'v> From<u128> for ValueBag<'v>
[src]
impl<'v> From<u16> for ValueBag<'v>
[src]
impl<'v> From<u32> for ValueBag<'v>
[src]
impl<'v> From<u64> for ValueBag<'v>
[src]
impl<'v> From<u8> for ValueBag<'v>
[src]
impl<'v> From<usize> for ValueBag<'v>
[src]
Auto Trait Implementations
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,