Coverage Report

Created: 2026-06-28 08:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/value-bag-1.12.0/src/fill.rs
Line
Count
Source
1
//! Deferred value initialization.
2
//!
3
//! The [`Fill`] trait is a way to bridge APIs that may not be directly
4
//! compatible with other constructor methods.
5
//!
6
//! The `Fill` trait is automatically implemented for closures, so can usually
7
//! be used in libraries that can't implement the trait themselves.
8
//!
9
//! ```
10
//! use value_bag::{ValueBag, fill::Slot};
11
//!
12
//! let value = ValueBag::from_fill(&|slot: Slot| {
13
//!     #[derive(Debug)]
14
//!     struct MyShortLivedValue;
15
//!
16
//!     slot.fill_debug(&MyShortLivedValue)
17
//! });
18
//!
19
//! assert_eq!("MyShortLivedValue", format!("{:?}", value));
20
//! ```
21
//!
22
//! The trait can also be implemented manually:
23
//!
24
//! ```
25
//! # use std::fmt::Debug;
26
//! use value_bag::{ValueBag, Error, fill::{Slot, Fill}};
27
//!
28
//! struct FillDebug;
29
//!
30
//! impl Fill for FillDebug {
31
//!     fn fill(&self, slot: Slot) -> Result<(), Error> {
32
//!         slot.fill_debug(&42i64 as &dyn Debug)
33
//!     }
34
//! }
35
//!
36
//! let value = ValueBag::from_fill(&FillDebug);
37
//!
38
//! assert_eq!(None, value.to_i64());
39
//! ```
40
41
use crate::std::fmt;
42
43
use super::internal::{Internal, InternalVisitor};
44
use super::{Error, ValueBag};
45
46
impl<'v> ValueBag<'v> {
47
    /// Get a value from a fillable slot.
48
0
    pub const fn from_fill<T>(value: &'v T) -> Self
49
0
    where
50
0
        T: Fill,
51
    {
52
0
        ValueBag {
53
0
            inner: Internal::Fill(value),
54
0
        }
55
0
    }
56
}
57
58
/// A type that requires extra work to convert into a [`ValueBag`](../struct.ValueBag.html).
59
///
60
/// This trait is an advanced initialization API.
61
/// It's intended for erased values coming from other logging frameworks that may need
62
/// to perform extra work to determine the concrete type to use.
63
pub trait Fill {
64
    /// Fill a value.
65
    fn fill(&self, slot: Slot) -> Result<(), Error>;
66
}
67
68
impl<F> Fill for F
69
where
70
    F: Fn(Slot) -> Result<(), Error>,
71
{
72
0
    fn fill(&self, slot: Slot) -> Result<(), Error> {
73
0
        (self)(slot)
74
0
    }
75
}
76
77
/// A value slot to fill using the [`Fill`](trait.Fill.html) trait.
78
pub struct Slot<'s, 'f> {
79
    visitor: &'s mut dyn InternalVisitor<'f>,
80
}
81
82
impl<'s, 'f> fmt::Debug for Slot<'s, 'f> {
83
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84
0
        f.debug_struct("Slot").finish()
85
0
    }
86
}
87
88
impl<'s, 'f> Slot<'s, 'f> {
89
0
    pub(crate) fn new(visitor: &'s mut dyn InternalVisitor<'f>) -> Self {
90
0
        Slot { visitor }
91
0
    }
92
93
0
    pub(crate) fn fill<F>(self, f: F) -> Result<(), Error>
94
0
    where
95
0
        F: FnOnce(&mut dyn InternalVisitor<'f>) -> Result<(), Error>,
96
    {
97
0
        f(self.visitor)
98
0
    }
99
100
    /// Fill the slot with a value.
101
    ///
102
    /// The given value doesn't need to satisfy any particular lifetime constraints.
103
0
    pub fn fill_any<T>(self, value: T) -> Result<(), Error>
104
0
    where
105
0
        T: Into<ValueBag<'f>>,
106
    {
107
0
        self.fill(|visitor| value.into().inner.internal_visit(visitor))
108
0
    }
109
}
110
111
#[cfg(test)]
112
mod tests {
113
    #[cfg(target_arch = "wasm32")]
114
    use wasm_bindgen_test::*;
115
116
    use super::*;
117
    use crate::std::string::ToString;
118
119
    #[test]
120
    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
121
    fn fill_value_borrowed() {
122
        struct TestFill;
123
124
        impl Fill for TestFill {
125
            fn fill(&self, slot: Slot) -> Result<(), Error> {
126
                let dbg = &1 as &dyn fmt::Debug;
127
128
                slot.fill_debug(dbg)
129
            }
130
        }
131
132
        assert_eq!("1", ValueBag::from_fill(&TestFill).to_string());
133
    }
134
135
    #[test]
136
    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
137
    fn fill_cast() {
138
        struct TestFill;
139
140
        impl Fill for TestFill {
141
            fn fill(&self, slot: Slot) -> Result<(), Error> {
142
                slot.fill_any("a string")
143
            }
144
        }
145
146
        assert_eq!(
147
            "a string",
148
            ValueBag::from_fill(&TestFill)
149
                .to_borrowed_str()
150
                .expect("invalid value")
151
        );
152
    }
153
154
    #[test]
155
    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
156
    fn fill_fn_cast() {
157
        assert_eq!(
158
            42u64,
159
            ValueBag::from_fill(&|slot: Slot| slot.fill_any(42u64))
160
                .to_u64()
161
                .unwrap()
162
        );
163
    }
164
165
    #[test]
166
    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
167
    fn fill_fn_borrowed() {
168
        #[derive(Debug)]
169
        struct MyValue;
170
171
        let value = MyValue;
172
        assert_eq!(
173
            format!("{:?}", value),
174
            format!(
175
                "{:?}",
176
                ValueBag::from_fill(&|slot: Slot| slot.fill_debug(&value))
177
            )
178
        );
179
    }
180
}