A ValueBag is an anonymous structured value that supports casting, downcasting, formatting, and serializing. The producer of a ValueBag and its eventual consumer don't need to agree on a serialization contract. Any translation is handled internally by ValueBag.
Say we capture an i32 using its Display implementation as a ValueBag:
let bag = ValueBag::capture_display(42);That value can then be cast to a concrete integer type, like u64:
let num = bag.as_u64().unwrap();
assert_eq!(42, num);It could also be serialized as a number using serde:
let num = serde_json::to_value(&bag).unwrap();
assert!(num.is_number());It works for more complex types too. Say we derive sval::Value on a type and capture it as a ValueBag:
#[derive(Value)]
struct Work {
id: u64,
description: String,
}
let work = Work {
id: 123,
description: String::from("do the work"),
}
let bag = ValueBag::capture_sval2(&work);We could still serialize that value using serde without losing structure:
let obj = serde_json::to_value(&bag).unwrap();
assert!(obj.is_object());It could also be formatted using Display:
assert_eq!("Work { id: 123, description: \"do the work\" }", bag.to_string());The tradeoff in all this is that ValueBag needs to depend on the serialization frameworks (sval, serde, and std::fmt) that it supports, instead of just providing an API of its own for others to plug into. Doing this lets ValueBag guarantee everything will always line up, and keep its own public API narrow.
Add the value-bag crate to your Cargo.toml:
[dependencies.value-bag]
version = "1.11.1"You'll probably also want to add a feature for either sval (if you're in a no-std environment) or serde (if you need to integrate with other code that uses serde):
[dependencies.value-bag]
version = "1.11.1"
features = ["sval2"][dependencies.value-bag]
version = "1.11.1"
features = ["serde1"]Then you're ready to capture anonymous values!
#[derive(Serialize)]
struct MyValue {
title: String,
description: String,
version: u32,
}
// Capture a value that implements `serde::Serialize`
let bag = ValueBag::capture_serde1(&my_value);
// Print the contents of the value bag
println!("{:?}", bag);The value-bag crate is no-std by default, and offers the following Cargo features:
std: Enable support for the standard library. This allows more types to be captured in aValueBag.error: Enable support for capturingstd::error::Errors. Impliesstd.sval: Enable support for using thesvalserialization framework for inspectingValueBags by implementingsval::value::Value. Impliessval2.sval2: Enable support for the stable2.x.xversion ofsval.
serde: Enable support for using theserdeserialization framework for inspectingValueBags by implementingserde::Serialize. Impliesstdandserde1.serde1: Enable support for the stable1.x.xversion ofserde.
owned: Add support for bufferingValueBags into an ownedSend + Syncvariant.seq: Add support for working with sequences without needing to go through a full serialization framework.test: Add test helpers for inspecting the shape of the value inside aValueBag.