1use crate::{
2 internal::{self, Internal},
3 std::sync::Arc,
4 ValueBag,
5};
6
7#[derive(Clone)]
16pub struct OwnedValueBag {
17 inner: internal::owned::OwnedInternal,
18}
19
20impl<'v> ValueBag<'v> {
21 pub fn to_owned(&self) -> OwnedValueBag {
23 OwnedValueBag {
24 inner: self.inner.to_owned(),
25 }
26 }
27
28 pub fn to_shared(&self) -> OwnedValueBag {
31 self.to_owned().into_shared()
32 }
33}
34
35impl ValueBag<'static> {
36 pub fn capture_shared_debug<T>(value: T) -> Self
43 where
44 T: internal::fmt::Debug + Send + Sync + 'static,
45 {
46 Self::try_capture_owned(&value).unwrap_or_else(|| ValueBag {
47 inner: Internal::SharedDebug(Arc::new(value)),
48 })
49 }
50
51 pub fn capture_shared_display<T>(value: T) -> Self
58 where
59 T: internal::fmt::Display + Send + Sync + 'static,
60 {
61 Self::try_capture_owned(&value).unwrap_or_else(|| ValueBag {
62 inner: Internal::SharedDisplay(Arc::new(value)),
63 })
64 }
65
66 #[cfg(feature = "error")]
70 pub fn capture_shared_error<T>(value: T) -> Self
71 where
72 T: internal::error::Error + Send + Sync + 'static,
73 {
74 ValueBag {
75 inner: Internal::SharedError(Arc::new(value)),
76 }
77 }
78
79 #[cfg(feature = "sval2")]
86 pub fn capture_shared_sval2<T>(value: T) -> Self
87 where
88 T: value_bag_sval2::lib::Value + Send + Sync + 'static,
89 {
90 Self::try_capture_owned(&value).unwrap_or(ValueBag {
91 inner: Internal::SharedSval2(Arc::new(value)),
92 })
93 }
94
95 #[cfg(feature = "serde1")]
102 pub fn capture_shared_serde1<T>(value: T) -> Self
103 where
104 T: value_bag_serde1::lib::Serialize + Send + Sync + 'static,
105 {
106 Self::try_capture_owned(&value).unwrap_or(ValueBag {
107 inner: Internal::SharedSerde1(Arc::new(value)),
108 })
109 }
110
111 #[cfg(feature = "seq")]
115 pub fn capture_shared_seq_slice<I, T>(value: I) -> Self
116 where
117 I: AsRef<[T]> + Send + Sync + 'static,
118 T: Send + Sync + 'static,
119 for<'v> &'v T: Into<ValueBag<'v>>,
120 {
121 use crate::{
122 internal::seq::Visitor,
123 std::{marker::PhantomData, ops::ControlFlow},
124 };
125
126 struct OwnedSeqSlice<I: ?Sized, T>(PhantomData<[T]>, I);
127
128 impl<I, T> internal::seq::Seq for OwnedSeqSlice<I, T>
129 where
130 I: AsRef<[T]> + ?Sized,
131 for<'v> &'v T: Into<ValueBag<'v>>,
132 {
133 fn visit(&self, visitor: &mut dyn Visitor<'_>) {
134 for v in self.1.as_ref().iter() {
135 if let ControlFlow::Break(()) = visitor.element(v.into()) {
136 return;
137 }
138 }
139 }
140 }
141
142 Self::try_capture_owned(&value).unwrap_or(ValueBag {
143 inner: Internal::SharedSeq(Arc::new(OwnedSeqSlice(PhantomData, value))),
144 })
145 }
146}
147
148impl OwnedValueBag {
149 pub const fn by_ref(&self) -> ValueBag<'_> {
158 ValueBag {
159 inner: self.inner.by_ref(),
160 }
161 }
162
163 pub fn into_shared(self) -> Self {
167 OwnedValueBag {
168 inner: self.inner.into_shared(),
169 }
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 #[cfg(target_arch = "wasm32")]
176 use wasm_bindgen_test::*;
177
178 use super::*;
179
180 use crate::{
181 fill,
182 std::{mem, string::ToString},
183 };
184
185 const SIZE_LIMIT_U64: usize = 4;
186
187 #[test]
188 fn is_send_sync() {
189 fn assert<T: Send + Sync + 'static>() {}
190
191 assert::<OwnedValueBag>();
192 }
193
194 #[test]
195 fn owned_value_bag_size() {
196 let size = mem::size_of::<OwnedValueBag>();
197 let limit = mem::size_of::<u64>() * SIZE_LIMIT_U64;
198
199 if size > limit {
200 panic!(
201 "`OwnedValueBag` size ({} bytes) is too large (expected up to {} bytes)",
202 size, limit,
203 );
204 }
205 }
206
207 #[test]
208 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
209 fn fill_to_owned() {
210 let value = ValueBag::from_fill(&|slot: fill::Slot| slot.fill_any(42u64)).to_owned();
211
212 assert!(matches!(
213 value.inner,
214 internal::owned::OwnedInternal::BigUnsigned(42)
215 ));
216 }
217
218 #[test]
219 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
220 fn fill_to_shared() {
221 let value = ValueBag::from_fill(&|slot: fill::Slot| slot.fill_any(42u64)).to_shared();
222
223 assert!(matches!(
224 value.inner,
225 internal::owned::OwnedInternal::BigUnsigned(42)
226 ));
227 }
228
229 #[test]
230 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
231 fn fmt_to_owned() {
232 let debug = ValueBag::from_debug(&"a value").to_owned();
233 let display = ValueBag::from_display(&"a value").to_owned();
234
235 assert!(matches!(
236 debug.inner,
237 internal::owned::OwnedInternal::Debug(_)
238 ));
239 assert!(matches!(
240 display.inner,
241 internal::owned::OwnedInternal::Display(_)
242 ));
243
244 assert_eq!("\"a value\"", debug.to_string());
245 assert_eq!("a value", display.to_string());
246
247 let debug = debug.by_ref();
248 let display = display.by_ref();
249
250 assert!(matches!(debug.inner, internal::Internal::AnonDebug(_)));
251 assert!(matches!(display.inner, internal::Internal::AnonDisplay(_)));
252 }
253
254 #[test]
255 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
256 fn fmt_to_shared() {
257 let debug = ValueBag::from_debug(&"a value").to_shared();
258 let display = ValueBag::from_display(&"a value").to_shared();
259
260 assert!(matches!(
261 debug.inner,
262 internal::owned::OwnedInternal::SharedDebug(_)
263 ));
264 assert!(matches!(
265 display.inner,
266 internal::owned::OwnedInternal::SharedDisplay(_)
267 ));
268 }
269
270 #[test]
271 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
272 fn owned_fmt_to_owned() {
273 let debug = ValueBag::capture_shared_debug("a value".to_string()).to_owned();
274 let display = ValueBag::capture_shared_display("a value".to_string()).to_owned();
275
276 assert!(matches!(
277 debug.inner,
278 internal::owned::OwnedInternal::SharedDebug(_)
279 ));
280 assert!(matches!(
281 display.inner,
282 internal::owned::OwnedInternal::SharedDisplay(_)
283 ));
284
285 assert_eq!("\"a value\"", debug.to_string());
286 assert_eq!("a value", display.to_string());
287
288 let debug = debug.by_ref();
289 let display = display.by_ref();
290
291 assert!(matches!(debug.inner, internal::Internal::SharedRefDebug(_)));
292 assert!(matches!(
293 display.inner,
294 internal::Internal::SharedRefDisplay(_)
295 ));
296 }
297
298 #[test]
299 #[cfg(feature = "error")]
300 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
301 fn error_to_owned() {
302 use crate::std::io;
303
304 let value =
305 ValueBag::from_dyn_error(&io::Error::new(io::ErrorKind::Other, "something failed!"))
306 .to_owned();
307
308 assert!(matches!(
309 value.inner,
310 internal::owned::OwnedInternal::Error(_)
311 ));
312
313 let value = value.by_ref();
314
315 assert!(matches!(value.inner, internal::Internal::AnonError(_)));
316
317 assert!(value.to_borrowed_error().is_some());
318 }
319
320 #[test]
321 #[cfg(feature = "error")]
322 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
323 fn error_to_shared() {
324 use crate::std::io;
325
326 let value =
327 ValueBag::from_dyn_error(&io::Error::new(io::ErrorKind::Other, "something failed!"))
328 .to_shared();
329
330 assert!(matches!(
331 value.inner,
332 internal::owned::OwnedInternal::SharedError(_)
333 ));
334 }
335
336 #[test]
337 #[cfg(feature = "error")]
338 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
339 fn owned_error_to_owned() {
340 use crate::std::io;
341
342 let value = ValueBag::capture_shared_error(io::Error::new(
343 io::ErrorKind::Other,
344 "something failed!",
345 ))
346 .to_owned();
347
348 assert!(matches!(
349 value.inner,
350 internal::owned::OwnedInternal::SharedError(_)
351 ));
352
353 let value = value.by_ref();
354
355 assert!(matches!(value.inner, internal::Internal::SharedRefError(_)));
356 }
357
358 #[test]
359 #[cfg(feature = "serde1")]
360 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
361 fn serde1_to_owned() {
362 let value = ValueBag::from_serde1(&42u64).to_owned();
363
364 assert!(matches!(
365 value.inner,
366 internal::owned::OwnedInternal::Serde1(_)
367 ));
368
369 let value = value.by_ref();
370
371 assert!(matches!(value.inner, internal::Internal::AnonSerde1(_)));
372 }
373
374 #[test]
375 #[cfg(feature = "serde1")]
376 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
377 fn serde1_to_shared() {
378 let value = ValueBag::from_serde1(&42u64).to_shared();
379
380 assert!(matches!(
381 value.inner,
382 internal::owned::OwnedInternal::SharedSerde1(_)
383 ));
384 }
385
386 #[test]
387 #[cfg(feature = "serde1")]
388 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
389 fn owned_serde1_to_owned() {
390 let value = ValueBag::capture_shared_serde1("a value".to_string()).to_owned();
391
392 assert!(matches!(
393 value.inner,
394 internal::owned::OwnedInternal::SharedSerde1(_)
395 ));
396
397 let value = value.by_ref();
398
399 assert!(matches!(
400 value.inner,
401 internal::Internal::SharedRefSerde1(_)
402 ));
403 }
404
405 #[test]
406 #[cfg(feature = "sval2")]
407 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
408 fn sval2_to_owned() {
409 let value = ValueBag::from_sval2(&42u64).to_owned();
410
411 assert!(matches!(
412 value.inner,
413 internal::owned::OwnedInternal::Sval2(_)
414 ));
415
416 let value = value.by_ref();
417
418 assert!(matches!(value.inner, internal::Internal::AnonSval2(_)));
419 }
420
421 #[test]
422 #[cfg(feature = "sval2")]
423 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
424 fn sval2_to_shared() {
425 let value = ValueBag::from_sval2(&42u64).to_shared();
426
427 assert!(matches!(
428 value.inner,
429 internal::owned::OwnedInternal::SharedSval2(_)
430 ));
431 }
432
433 #[test]
434 #[cfg(feature = "sval2")]
435 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
436 fn owned_sval2_to_owned() {
437 let value = ValueBag::capture_shared_sval2("a value".to_string()).to_owned();
438
439 assert!(matches!(
440 value.inner,
441 internal::owned::OwnedInternal::SharedSval2(_)
442 ));
443
444 let value = value.by_ref();
445
446 assert!(matches!(value.inner, internal::Internal::SharedRefSval2(_)));
447 }
448
449 #[test]
450 #[cfg(feature = "seq")]
451 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
452 fn seq_to_owned() {
453 let value = ValueBag::from_seq_slice(&[1, 2, 3]).to_owned();
454
455 assert!(matches!(
456 value.inner,
457 internal::owned::OwnedInternal::Seq(_)
458 ));
459
460 let value = value.by_ref();
461
462 assert!(matches!(value.inner, internal::Internal::AnonSeq(_)));
463 }
464
465 #[test]
466 #[cfg(feature = "seq")]
467 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
468 fn seq_to_shared() {
469 let value = ValueBag::from_seq_slice(&[1, 2, 3]).to_shared();
470
471 assert!(matches!(
472 value.inner,
473 internal::owned::OwnedInternal::SharedSeq(_)
474 ));
475 }
476
477 #[test]
478 #[cfg(feature = "seq")]
479 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
480 fn owned_seq_to_owned() {
481 let value = ValueBag::capture_shared_seq_slice(vec![1, 2, 3]).to_owned();
482
483 assert!(matches!(
484 value.inner,
485 internal::owned::OwnedInternal::SharedSeq(_)
486 ));
487
488 let value = value.by_ref();
489
490 assert!(matches!(value.inner, internal::Internal::SharedRefSeq(_)));
491 }
492}