[][src]Struct value_bag::ValueBag

pub struct ValueBag<'v> { /* fields omitted */ }

A dynamic structured value.

Capturing values

There are a few ways to capture a value:

  • Using the ValueBag::capture_* and ValueBag::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(&timestamp);

assert!(value.downcast_ref::<SystemTime>().is_some());

Implementations

impl<'v> ValueBag<'v>[src]

pub fn from_fill<T>(value: &'v T) -> Self where
    T: Fill
[src]

Get a value from a fillable slot.

impl<'v> ValueBag<'v>[src]

pub fn to_str(&self) -> Option<Cow<'_, str>>[src]

Try get a str from this value.

This method is cheap for primitive types, but may call arbitrary serialization implementations for complex ones. If the serialization implementation produces a short lived string it will be allocated.

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_error<T>(value: &'v T) -> Self where
    T: Error + 'static, 
[src]

Get a value from an error.

pub fn from_dyn_error(value: &'v (dyn Error + 'static)) -> Self[src]

Get a value from an erased value.

pub fn to_borrowed_error(&self) -> Option<&(dyn Error + 'static)>[src]

Try get an error from this value.

impl<'v> ValueBag<'v>[src]

pub fn capture_debug<T>(value: &'v T) -> Self where
    T: Debug + 'static, 
[src]

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]

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]

Get a value from a debuggable type without capturing support.

pub fn from_display<T>(value: &'v T) -> Self where
    T: Display
[src]

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]

pub fn capture_serde1<T>(value: &'v T) -> Self where
    T: Serialize + 'static, 
[src]

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.

pub fn from_serde1<T>(value: &'v T) -> Self where
    T: Serialize
[src]

Get a value from a structured type without capturing support.

impl<'v> ValueBag<'v>[src]

pub fn capture_sval1<T>(value: &'v T) -> Self where
    T: Value + 'static, 
[src]

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.

pub fn from_sval1<T>(value: &'v T) -> Self where
    T: Value
[src]

Get a value from a structured type without capturing support.

pub fn from_dyn_sval1(value: &'v dyn Value) -> Self[src]

Get a value from an erased structured type.

impl<'v> ValueBag<'v>[src]

pub fn visit(&self, visitor: impl Visit<'v>) -> Result<(), Error>[src]

impl<'v> ValueBag<'v>[src]

pub fn to_token(&self) -> Token[src]

Convert the value bag into a token for testing.

This isn't a general-purpose API for working with values outside of testing.

Trait Implementations

impl<'v> Clone for ValueBag<'v>[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]

impl<'v> Serialize for ValueBag<'v>[src]

impl<'v> Value for ValueBag<'v>[src]

Auto Trait Implementations

impl<'v> !RefUnwindSafe for ValueBag<'v>[src]

impl<'v> !Send for ValueBag<'v>[src]

impl<'v> !Sync for ValueBag<'v>[src]

impl<'v> Unpin for ValueBag<'v>[src]

impl<'v> !UnwindSafe for ValueBag<'v>[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Serialize for T where
    T: Serialize + ?Sized
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.