1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! Structured values.


#![cfg_attr(value_bag_const_type_id, feature(const_type_id))]

#![no_std]

#[cfg(any(feature = "std", test))]
#[macro_use]
#[allow(unused_imports)]
extern crate std;

#[cfg(not(any(feature = "std", test)))]
#[macro_use]
#[allow(unused_imports)]
extern crate core as std;

mod error;
mod fill;
mod impls;
mod internal;

#[cfg(test)]
mod test;

pub use self::{
    error::Error,
    fill::{Fill, Slot},
};

use self::internal::{Inner, Primitive, Visitor};

/// A dynamic structured value.

///

/// # Capturing values

///

/// There are a few ways to capture a value:

///

/// - Using the `ValueBag::capture_*` 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_i32());

/// ```

///

/// ## Using the standard `From` trait

///

/// Standard types that implement `ToValue` also implement `From`.

///

/// ```

/// use value_bag::ValueBag;

///

/// let value = ValueBag::from(42i32);

///

/// assert_eq!(Some(42), value.to_i32());

/// ```

///

/// ```

/// # use std::fmt::Debug;

/// use value_bag::ValueBag;

///

/// let value = ValueBag::from(&42i32 as &dyn Debug);

///

/// assert_eq!(None, value.to_i32());

/// ```

///

/// ## Using the `Fill` API

///

/// The `Fill` trait is a way to bridge APIs that may not be directly

/// compatible with other constructor methods.

///

/// ```

/// use value_bag::{ValueBag, Slot, Fill, Error};

///

/// struct FillSigned;

///

/// impl Fill for FillSigned {

///     fn fill(&self, slot: &mut Slot) -> Result<(), Error> {

///         slot.fill_any(42i32)

///     }

/// }

///

/// let value = ValueBag::from_fill(&FillSigned);

///

/// assert_eq!(Some(42), value.to_i32());

/// ```

///

/// ```

/// # use std::fmt::Debug;

/// use value_bag::{ValueBag, Slot, Fill, Error};

///

/// 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_i32());

/// ```

///

/// # Inspecting values

///

/// Once you have a `ValueBag` there are also a few ways to inspect it:

///

/// - Using the `Debug`, `Display`, `Serialize`, and `Stream` trait implementations.

/// - Using the `ValueBag::to_*` methods.

/// - Using the `ValueBag::downcast_ref` method.

#[derive(Clone)]
pub struct ValueBag<'v> {
    inner: Inner<'v>,
}

impl<'v> ValueBag<'v> {
    /// Get a value from an internal primitive.

    fn from_primitive<T>(value: T) -> Self
    where
        T: Into<Primitive<'v>>,
    {
        ValueBag {
            inner: Inner::Primitive {
                value: value.into(),
            },
        }
    }

    /// Visit the value using an internal visitor.

    fn visit<'a>(&'a self, visitor: &mut dyn Visitor<'a>) -> Result<(), Error> {
        self.inner.visit(visitor)
    }
}