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/sval_ref-2.19.0/src/lib.rs
Line
Count
Source
1
/*!
2
A variant of [`sval::Value`] for types that store references internally.
3
4
# Deriving [`ValueRef`]
5
6
Add the `ref` feature to `sval_derive`:
7
8
```toml
9
[dependencies.sval_derive]
10
version = "2.19.0"
11
features = ["ref"]
12
```
13
14
and include the `#[sval(ref)]` attribute when deriving `Value`:
15
16
```rust,ignore
17
#[derive(Value)]
18
#[sval(ref)]
19
pub struct MyData<'a> {
20
    #[sval(outer_ref)]
21
    data: &'a str,
22
}
23
```
24
25
Fields are streamed as computed by default.
26
Use the `#[sval(outer_ref)]` attribute for fields with external references like `&'a str`, and the `#[sval(inner_ref)]` attribute for fields with internal references like `Data<'a>`.
27
*/
28
29
#![doc(html_logo_url = "https://raw.githubusercontent.com/sval-rs/sval/main/asset/logo.svg")]
30
#![cfg_attr(not(test), no_std)]
31
#![deny(missing_docs)]
32
33
#[cfg(feature = "std")]
34
extern crate std;
35
36
#[cfg(all(feature = "alloc", not(feature = "std")))]
37
extern crate alloc;
38
#[cfg(all(feature = "alloc", not(feature = "std")))]
39
extern crate core;
40
41
#[cfg(all(feature = "alloc", not(feature = "std")))]
42
mod std {
43
    pub use crate::{
44
        alloc::{borrow, boxed, collections, string, vec},
45
        core::{convert, fmt, hash, marker, mem, ops, result, str, write},
46
    };
47
}
48
49
#[cfg(all(not(feature = "alloc"), not(feature = "std")))]
50
extern crate core as std;
51
52
mod seq;
53
54
/**
55
Stream a value through a stream.
56
*/
57
0
pub fn stream_ref<'sval>(
58
0
    stream: &mut (impl Stream<'sval> + ?Sized),
59
0
    value: impl ValueRef<'sval>,
60
0
) -> Result {
61
0
    value.stream_ref(stream)
62
0
}
Unexecuted instantiation: sval_ref::stream_ref::<dyn sval_dynamic::stream::Stream, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<dyn sval_dynamic::stream::Stream, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<dyn sval_dynamic::stream::Stream, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::tag::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::tag::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::tag::Extract, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_f32::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_f32::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_f32::Extract, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_f64::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_f64::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_f64::Extract, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_bool::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_bool::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_bool::Extract, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_i128::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_i128::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_i128::Extract, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_text::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_text::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_text::Extract, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_u128::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_u128::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_u128::Extract, &sval_buffer::fragments::BinaryBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_binary::Extract, &sval_buffer::value::ValueSlice>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_binary::Extract, &sval_buffer::fragments::TextBuf>
Unexecuted instantiation: sval_ref::stream_ref::<sval::value::default_value::to_binary::Extract, &sval_buffer::fragments::BinaryBuf>
63
64
/**
65
Wrap an [`sval::Value`] in a [`ValueRef`]
66
*/
67
pub fn to_ref<'sval, V: sval::Value + ?Sized>(value: &'sval V) -> Ref<&'sval V> {
68
    Ref::new(value)
69
}
70
71
use sval::{Result, Stream, Value};
72
73
/**
74
Adapt an [`sval::Value`] into a [`ValueRef`].
75
*/
76
#[repr(transparent)]
77
#[derive(Debug, Clone, Copy)]
78
pub struct Ref<V: ?Sized>(V);
79
80
impl<V> Ref<V> {
81
    /**
82
    Wrap a value.
83
    */
84
    pub fn new(value: V) -> Self {
85
        Ref(value)
86
    }
87
88
    /**
89
    Get a reference to the underlying value.
90
    */
91
    pub fn inner(&self) -> &V {
92
        &self.0
93
    }
94
95
    /**
96
    Take ownership of the underlying value.
97
    */
98
    pub fn into_inner(self) -> V {
99
        self.0
100
    }
101
}
102
103
impl<V: ?Sized> Ref<V> {
104
    /**
105
    Get a borrowed wrapper over a borrowed value.
106
    */
107
    pub fn new_borrowed<'a>(value: &'a V) -> &'a Ref<V> {
108
        // SAFETY: `&'a V` and `&'a Ref<V>` have the same ABI
109
        unsafe { &*(value as *const _ as *const Ref<V>) }
110
    }
111
}
112
113
impl<V: sval::Value> sval::Value for Ref<V> {
114
    fn stream<'sval, S: Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> Result {
115
        self.0.stream(stream)
116
    }
117
118
    fn tag(&self) -> Option<sval::Tag> {
119
        self.0.tag()
120
    }
121
122
    fn to_bool(&self) -> Option<bool> {
123
        self.0.to_bool()
124
    }
125
126
    fn to_f32(&self) -> Option<f32> {
127
        self.0.to_f32()
128
    }
129
130
    fn to_f64(&self) -> Option<f64> {
131
        self.0.to_f64()
132
    }
133
134
    fn to_i8(&self) -> Option<i8> {
135
        self.0.to_i8()
136
    }
137
138
    fn to_i16(&self) -> Option<i16> {
139
        self.0.to_i16()
140
    }
141
142
    fn to_i32(&self) -> Option<i32> {
143
        self.0.to_i32()
144
    }
145
146
    fn to_i64(&self) -> Option<i64> {
147
        self.0.to_i64()
148
    }
149
150
    fn to_i128(&self) -> Option<i128> {
151
        self.0.to_i128()
152
    }
153
154
    fn to_u8(&self) -> Option<u8> {
155
        self.0.to_u8()
156
    }
157
158
    fn to_u16(&self) -> Option<u16> {
159
        self.0.to_u16()
160
    }
161
162
    fn to_u32(&self) -> Option<u32> {
163
        self.0.to_u32()
164
    }
165
166
    fn to_u64(&self) -> Option<u64> {
167
        self.0.to_u64()
168
    }
169
170
    fn to_u128(&self) -> Option<u128> {
171
        self.0.to_u128()
172
    }
173
174
    fn to_text(&self) -> Option<&str> {
175
        self.0.to_text()
176
    }
177
178
    fn to_binary(&self) -> Option<&[u8]> {
179
        self.0.to_binary()
180
    }
181
}
182
183
impl<'sval, V: sval::Value + ?Sized> ValueRef<'sval> for Ref<&'sval V> {
184
    fn stream_ref<S: Stream<'sval> + ?Sized>(&self, stream: &mut S) -> Result {
185
        self.0.stream(stream)
186
    }
187
}
188
189
/**
190
A producer of structured data that stores a reference internally.
191
192
This trait is a variant of [`Value`] for wrapper types that keep a reference to a value internally.
193
In `Value`, the `'sval` lifetime comes from the borrow of `&'sval self`. In `ValueRef`, it comes
194
from the `'sval` lifetime in the trait itself.
195
*/
196
pub trait ValueRef<'sval>: Value {
197
    /**
198
    Stream this value through a [`Stream`].
199
    */
200
    fn stream_ref<S: Stream<'sval> + ?Sized>(&self, stream: &mut S) -> Result;
201
}
202
203
macro_rules! impl_value_ref_forward {
204
    ({ $($r:tt)* } => $bind:ident => { $($forward:tt)* }) => {
205
        $($r)* {
206
0
            fn stream_ref<S: Stream<'sval> + ?Sized>(&self, stream: &mut S) -> Result {
207
0
                let $bind = self;
208
0
                ($($forward)*).stream_ref(stream)
209
0
            }
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<dyn sval_dynamic::stream::Stream>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::tag::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_f32::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_f64::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_bool::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_i128::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_text::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_u128::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::TextBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_binary::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<dyn sval_dynamic::stream::Stream>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::tag::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_f32::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_f64::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_bool::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_i128::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_text::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_u128::Extract>
Unexecuted instantiation: <&sval_buffer::fragments::BinaryBuf as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_binary::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<dyn sval_dynamic::stream::Stream>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::tag::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_f32::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_f64::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_bool::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_i128::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_text::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_u128::Extract>
Unexecuted instantiation: <&sval_buffer::value::ValueSlice as sval_ref::ValueRef>::stream_ref::<sval::value::default_value::to_binary::Extract>
210
        }
211
    };
212
}
213
214
impl_value_ref_forward!({impl<'sval, 'a, T: ValueRef<'sval> + ?Sized> ValueRef<'sval> for &'a T} => x => { **x });
215
216
#[cfg(feature = "alloc")]
217
mod alloc_support {
218
    use super::*;
219
220
    use crate::std::boxed::Box;
221
222
    impl_value_ref_forward!({impl<'sval, T: ValueRef<'sval> + ?Sized> ValueRef<'sval> for Box<T>} => x => { **x });
223
}
224
225
#[cfg(test)]
226
mod test {
227
    use crate::ValueRef;
228
    pub(crate) use sval_test::{assert_tokens, Token};
229
230
    pub(crate) fn assert_tokens_ref<'sval>(
231
        value: impl ValueRef<'sval>,
232
        tokens: &[sval_test::Token<'sval>],
233
    ) {
234
        let mut actual = sval_test::TokenBuf::new();
235
        value.stream_ref(&mut actual).unwrap();
236
237
        assert_eq!(tokens, actual.as_tokens());
238
    }
239
240
    pub(crate) struct Ref<T>(pub(crate) T);
241
242
    impl<T: sval::Value> sval::Value for Ref<T> {
243
        fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(
244
            &'sval self,
245
            stream: &mut S,
246
        ) -> sval::Result {
247
            self.0.stream(stream)
248
        }
249
    }
250
251
    impl<'sval, T: sval::Value + ?Sized> ValueRef<'sval> for Ref<&'sval T> {
252
        fn stream_ref<S: sval::Stream<'sval> + ?Sized>(&self, stream: &mut S) -> sval::Result {
253
            self.0.stream(stream)
254
        }
255
    }
256
257
    pub(crate) fn compat_case<'sval>(
258
        v: &'sval (impl sval::Value + ValueRef<'sval> + ?Sized),
259
        tokens: &[Token<'sval>],
260
    ) {
261
        assert_tokens_ref(v, tokens);
262
        assert_tokens(v, tokens);
263
    }
264
}