pub struct ValueBag<'v> { /* private fields */ }
Expand description
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: 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: 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 sval2
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 sval2
feature in your Cargo.toml
:
[dependencies.value-bag]
features = ["sval2"]
Then stream the contents of the ValueBag
using sval
.
use value_bag::ValueBag;
let value = ValueBag::from(42i64);
let json = sval_json::stream_to_string(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
.
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());
§Working with sequences
The seq
feature of value-bag
enables utilities for working with values that are sequences.
First, enable the seq
feature in your Cargo.toml
:
[dependencies.value-bag]
features = ["seq"]
Slices and arrays can be captured as sequences:
use value_bag::ValueBag;
let value = ValueBag::from_seq_slice(&[1, 2, 3]);
assert_eq!("[1,2,3]", serde_json::to_string(&value)?);
A sequence captured with either sval
or serde
can have its elements extracted:
use value_bag::ValueBag;
let value = ValueBag::from_serde1(&[1.0, 2.0, 3.0]);
let seq = value.to_f64_seq::<Vec<Option<f64>>>().ok_or("not a sequence")?;
assert_eq!(vec![Some(1.0), Some(2.0), Some(3.0)], seq);
Implementations§
source§impl ValueBag<'static>
impl ValueBag<'static>
sourcepub fn try_capture_owned<T>(value: &T) -> Option<Self>where
T: ?Sized + 'static,
pub fn try_capture_owned<T>(value: &T) -> Option<Self>where
T: ?Sized + 'static,
Try capture an owned raw value.
This method will return Some
if the value is a simple primitive
that can be captured without losing its structure. In other cases
this method will return None
.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn try_capture<T>(value: &'v T) -> Option<Self>where
T: ?Sized + 'static,
pub fn try_capture<T>(value: &'v T) -> Option<Self>where
T: ?Sized + 'static,
Try capture a raw value.
This method will return Some
if the value is a simple primitive
that can be captured without losing its structure. In other cases
this method will return None
.
sourcepub fn to_u64(&self) -> Option<u64>
pub fn to_u64(&self) -> Option<u64>
Try get a u64
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
sourcepub fn to_i64(&self) -> Option<i64>
pub fn to_i64(&self) -> Option<i64>
Try get a i64
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
sourcepub fn to_u128(&self) -> Option<u128>
pub fn to_u128(&self) -> Option<u128>
Try get a u128
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
sourcepub fn to_i128(&self) -> Option<i128>
pub fn to_i128(&self) -> Option<i128>
Try get a i128
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
sourcepub fn to_f64(&self) -> Option<f64>
pub fn to_f64(&self) -> Option<f64>
Try get a f64
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
This method is based on standard TryInto
conversions, and will
only return Some
if there’s a guaranteed lossless conversion between
the source and destination types. For a more lenient alternative, see
ValueBag::as_f64
.
sourcepub fn as_f64(&self) -> f64
pub fn as_f64(&self) -> f64
Get a f64
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
This method is like ValueBag::to_f64
except will always return
a f64
, regardless of the actual type of underlying value. For
numeric types, it will use a regular as
conversion, which may be lossy.
For non-numeric types it will return NaN
.
sourcepub fn to_bool(&self) -> Option<bool>
pub fn to_bool(&self) -> Option<bool>
Try get a bool
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
sourcepub fn to_char(&self) -> Option<char>
pub fn to_char(&self) -> Option<char>
Try get a char
from this value.
This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones.
sourcepub fn to_borrowed_str(&self) -> Option<&'v str>
pub fn to_borrowed_str(&self) -> Option<&'v str>
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.
sourcepub fn downcast_ref<T: 'static>(&self) -> Option<&T>
pub fn downcast_ref<T: 'static>(&self) -> Option<&T>
Try downcast this value to T
.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn capture_error<T>(value: &'v T) -> Selfwhere
T: Error + 'static,
pub fn capture_error<T>(value: &'v T) -> Selfwhere
T: Error + 'static,
Get a value from an error.
sourcepub const fn from_dyn_error(value: &'v (dyn Error + 'static)) -> Self
pub const fn from_dyn_error(value: &'v (dyn Error + 'static)) -> Self
Get a value from an erased value.
sourcepub fn to_borrowed_error(&self) -> Option<&'v (dyn Error + 'static)>
pub fn to_borrowed_error(&self) -> Option<&'v (dyn Error + 'static)>
Try get an error from this value.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn capture_debug<T>(value: &'v T) -> Selfwhere
T: Debug + 'static,
pub fn capture_debug<T>(value: &'v T) -> Selfwhere
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.
sourcepub fn capture_display<T>(value: &'v T) -> Selfwhere
T: Display + 'static,
pub fn capture_display<T>(value: &'v T) -> Selfwhere
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.
sourcepub const fn from_debug<T>(value: &'v T) -> Selfwhere
T: Debug,
pub const fn from_debug<T>(value: &'v T) -> Selfwhere
T: Debug,
Get a value from a debuggable type without capturing support.
sourcepub const fn from_display<T>(value: &'v T) -> Selfwhere
T: Display,
pub const fn from_display<T>(value: &'v T) -> Selfwhere
T: Display,
Get a value from a displayable type without capturing support.
sourcepub const fn from_dyn_debug(value: &'v dyn Debug) -> Self
pub const fn from_dyn_debug(value: &'v dyn Debug) -> Self
Get a value from a debuggable type without capturing support.
sourcepub const fn from_dyn_display(value: &'v dyn Display) -> Self
pub const fn from_dyn_display(value: &'v dyn Display) -> Self
Get a value from a displayable type without capturing support.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn to_str_seq<S: Default + Extend<Option<Cow<'v, str>>>>(&self) -> Option<S>
pub fn to_str_seq<S: Default + Extend<Option<Cow<'v, str>>>>(&self) -> Option<S>
Try get a collection S
of strings from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn from_seq_slice<I, T>(value: &'v I) -> Self
pub fn from_seq_slice<I, T>(value: &'v I) -> Self
Get a value from a sequence of values without capturing support.
sourcepub fn to_u64_seq<S: Default + Extend<Option<u64>>>(&self) -> Option<S>
pub fn to_u64_seq<S: Default + Extend<Option<u64>>>(&self) -> Option<S>
Try get a collection S
of u64
s from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
sourcepub fn to_i64_seq<S: Default + Extend<Option<i64>>>(&self) -> Option<S>
pub fn to_i64_seq<S: Default + Extend<Option<i64>>>(&self) -> Option<S>
Try get a collection S
of i64
s from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
sourcepub fn to_u128_seq<S: Default + Extend<Option<u128>>>(&self) -> Option<S>
pub fn to_u128_seq<S: Default + Extend<Option<u128>>>(&self) -> Option<S>
Try get a collection S
of u128
s from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
sourcepub fn to_i128_seq<S: Default + Extend<Option<i128>>>(&self) -> Option<S>
pub fn to_i128_seq<S: Default + Extend<Option<i128>>>(&self) -> Option<S>
Try get a collection S
of i128
s from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
sourcepub fn to_f64_seq<S: Default + Extend<Option<f64>>>(&self) -> Option<S>
pub fn to_f64_seq<S: Default + Extend<Option<f64>>>(&self) -> Option<S>
Try get a collection S
of f64
s from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
sourcepub fn as_f64_seq<S: Default + Extend<f64>>(&self) -> S
pub fn as_f64_seq<S: Default + Extend<f64>>(&self) -> S
Get a collection S
of f64
s from this value.
If this value is a sequence then the collection S
will be extended
with the conversion of each of its elements. The conversion is the
same as ValueBag::as_f64
.
If this value is not a sequence then this method will return an empty collection.
This is similar to ValueBag::to_f64_seq
, but can be more
convenient when there’s no need to distinguish between an empty
collection and a non-collection, or between f64
and non-f64
elements.
sourcepub fn to_bool_seq<S: Default + Extend<Option<bool>>>(&self) -> Option<S>
pub fn to_bool_seq<S: Default + Extend<Option<bool>>>(&self) -> Option<S>
Try get a collection S
of bool
s from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
sourcepub fn to_char_seq<S: Default + Extend<Option<char>>>(&self) -> Option<S>
pub fn to_char_seq<S: Default + Extend<Option<char>>>(&self) -> Option<S>
Try get a collection S
of char
s from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
sourcepub fn to_borrowed_str_seq<S: Default + Extend<Option<&'v str>>>(
&self,
) -> Option<S>
pub fn to_borrowed_str_seq<S: Default + Extend<Option<&'v str>>>( &self, ) -> Option<S>
Try get a collection S
of strings from this value.
If this value is a sequence then the collection S
will be extended
with the attempted conversion of each of its elements.
If this value is not a sequence then this method will return None
.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn capture_serde1<T>(value: &'v T) -> Selfwhere
T: Serialize + 'static,
pub fn capture_serde1<T>(value: &'v T) -> Selfwhere
T: Serialize + 'static,
Get a value from a structured type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Value
implementation.
sourcepub const fn from_serde1<T>(value: &'v T) -> Selfwhere
T: Serialize,
pub const fn from_serde1<T>(value: &'v T) -> Selfwhere
T: Serialize,
Get a value from a structured type without capturing support.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn capture_sval2<T>(value: &'v T) -> Selfwhere
T: Value + 'static,
pub fn capture_sval2<T>(value: &'v T) -> Selfwhere
T: Value + 'static,
Get a value from a structured type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Value
implementation.
sourcepub const fn from_sval2<T>(value: &'v T) -> Selfwhere
T: Value,
pub const fn from_sval2<T>(value: &'v T) -> Selfwhere
T: Value,
Get a value from a structured type without capturing support.
sourcepub const fn from_dyn_sval2(value: &'v dyn Value) -> Self
pub const fn from_dyn_sval2(value: &'v dyn Value) -> Self
Get a value from a structured type without capturing support.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn to_test_token(&self) -> TestToken
pub fn to_test_token(&self) -> TestToken
Convert the value bag into a token for testing.
This isn’t a general-purpose API for working with values outside of testing.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn to_owned(&self) -> OwnedValueBag
pub fn to_owned(&self) -> OwnedValueBag
Buffer this value into an OwnedValueBag
.
Buffer this value into an OwnedValueBag
, internally storing it
in an Arc
for cheap cloning.
source§impl ValueBag<'static>
impl ValueBag<'static>
Get a value from an owned, sharable, debuggable type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Debug
implementation.
The value will be stored in an Arc
for cheap cloning.
Get a value from an owned, sharable, displayable type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Display
implementation.
The value will be stored in an Arc
for cheap cloning.
Get a value from an owned, shared error.
The value will be stored in an Arc
for cheap cloning.
Get a value from an owned, shared, structured type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Value
implementation.
The value will be stored in an Arc
for cheap cloning.
Get a value from an owned, shared, structured type.
This method will attempt to capture the given value as a well-known primitive
before resorting to using its Value
implementation.
The value will be stored in an Arc
for cheap cloning.
Get a value from an owned, shared, sequence.
The value will be stored in an Arc
for cheap cloning.
source§impl<'v> ValueBag<'v>
impl<'v> ValueBag<'v>
sourcepub fn from_option(v: Option<impl Into<ValueBag<'v>>>) -> ValueBag<'v>
pub fn from_option(v: Option<impl Into<ValueBag<'v>>>) -> ValueBag<'v>
Get a ValueBag
from an Option
.
This method will return ValueBag::empty
if the value is None
.
sourcepub const fn from_usize(v: usize) -> ValueBag<'v>
pub const fn from_usize(v: usize) -> ValueBag<'v>
Get a ValueBag
from a usize
.
sourcepub const fn from_u128_ref(v: &'v u128) -> ValueBag<'v>
pub const fn from_u128_ref(v: &'v u128) -> ValueBag<'v>
Get a ValueBag
from a u128
.
sourcepub const fn from_isize(v: isize) -> ValueBag<'v>
pub const fn from_isize(v: isize) -> ValueBag<'v>
Get a ValueBag
from a isize
.
sourcepub const fn from_i128_ref(v: &'v i128) -> ValueBag<'v>
pub const fn from_i128_ref(v: &'v i128) -> ValueBag<'v>
Get a ValueBag
from a i128
.
Trait Implementations§
source§impl<'v> From<&'v OwnedValueBag> for ValueBag<'v>
impl<'v> From<&'v OwnedValueBag> for ValueBag<'v>
source§fn from(v: &'v OwnedValueBag) -> ValueBag<'v>
fn from(v: &'v OwnedValueBag) -> ValueBag<'v>
source§impl<'v> Value for ValueBag<'v>
impl<'v> Value for ValueBag<'v>
source§fn stream<'sval, S: Stream<'sval> + ?Sized>(&'sval self, s: &mut S) -> Result
fn stream<'sval, S: Stream<'sval> + ?Sized>(&'sval self, s: &mut S) -> Result
Stream
.source§fn to_f32(&self) -> Option<f32>
fn to_f32(&self) -> Option<f32>
Auto Trait Implementations§
impl<'v> Freeze for ValueBag<'v>
impl<'v> !RefUnwindSafe for ValueBag<'v>
impl<'v> !Send for ValueBag<'v>
impl<'v> !Sync for ValueBag<'v>
impl<'v> Unpin for ValueBag<'v>
impl<'v> !UnwindSafe for ValueBag<'v>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)