use crate::{
internal::{self, Internal},
std::sync::Arc,
ValueBag,
};
#[derive(Clone)]
pub struct OwnedValueBag {
inner: internal::owned::OwnedInternal,
}
impl<'v> ValueBag<'v> {
pub fn to_owned(&self) -> OwnedValueBag {
OwnedValueBag {
inner: self.inner.to_owned(),
}
}
pub fn to_shared(&self) -> OwnedValueBag {
self.to_owned().into_shared()
}
}
impl ValueBag<'static> {
pub fn capture_shared_debug<T>(value: T) -> Self
where
T: internal::fmt::Debug + Send + Sync + 'static,
{
Self::try_capture_owned(&value).unwrap_or_else(|| ValueBag {
inner: Internal::SharedDebug(Arc::new(value)),
})
}
pub fn capture_shared_display<T>(value: T) -> Self
where
T: internal::fmt::Display + Send + Sync + 'static,
{
Self::try_capture_owned(&value).unwrap_or_else(|| ValueBag {
inner: Internal::SharedDisplay(Arc::new(value)),
})
}
#[cfg(feature = "error")]
pub fn capture_shared_error<T>(value: T) -> Self
where
T: internal::error::Error + Send + Sync + 'static,
{
ValueBag {
inner: Internal::SharedError(Arc::new(value)),
}
}
#[cfg(feature = "sval2")]
pub fn capture_shared_sval2<T>(value: T) -> Self
where
T: value_bag_sval2::lib::Value + Send + Sync + 'static,
{
Self::try_capture_owned(&value).unwrap_or(ValueBag {
inner: Internal::SharedSval2(Arc::new(value)),
})
}
#[cfg(feature = "serde1")]
pub fn capture_shared_serde1<T>(value: T) -> Self
where
T: value_bag_serde1::lib::Serialize + Send + Sync + 'static,
{
Self::try_capture_owned(&value).unwrap_or(ValueBag {
inner: Internal::SharedSerde1(Arc::new(value)),
})
}
#[cfg(feature = "seq")]
pub fn capture_shared_seq_slice<I, T>(value: I) -> Self
where
I: AsRef<[T]> + Send + Sync + 'static,
T: Send + Sync + 'static,
for<'v> &'v T: Into<ValueBag<'v>>,
{
use crate::{
internal::seq::Visitor,
std::{marker::PhantomData, ops::ControlFlow},
};
struct OwnedSeqSlice<I: ?Sized, T>(PhantomData<[T]>, I);
impl<I, T> internal::seq::Seq for OwnedSeqSlice<I, T>
where
I: AsRef<[T]> + ?Sized,
for<'v> &'v T: Into<ValueBag<'v>>,
{
fn visit(&self, visitor: &mut dyn Visitor<'_>) {
for v in self.1.as_ref().iter() {
if let ControlFlow::Break(()) = visitor.element(v.into()) {
return;
}
}
}
}
Self::try_capture_owned(&value).unwrap_or(ValueBag {
inner: Internal::SharedSeq(Arc::new(OwnedSeqSlice(PhantomData, value))),
})
}
}
impl OwnedValueBag {
pub const fn by_ref(&self) -> ValueBag {
ValueBag {
inner: self.inner.by_ref(),
}
}
pub fn into_shared(self) -> Self {
OwnedValueBag {
inner: self.inner.into_shared(),
}
}
}
#[cfg(test)]
mod tests {
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;
use super::*;
use crate::{
fill,
std::{mem, string::ToString},
};
const SIZE_LIMIT_U64: usize = 4;
#[test]
fn is_send_sync() {
fn assert<T: Send + Sync + 'static>() {}
assert::<OwnedValueBag>();
}
#[test]
fn owned_value_bag_size() {
let size = mem::size_of::<OwnedValueBag>();
let limit = mem::size_of::<u64>() * SIZE_LIMIT_U64;
if size > limit {
panic!(
"`OwnedValueBag` size ({} bytes) is too large (expected up to {} bytes)",
size, limit,
);
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn fill_to_owned() {
let value = ValueBag::from_fill(&|slot: fill::Slot| slot.fill_any(42u64)).to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::BigUnsigned(42)
));
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn fill_to_shared() {
let value = ValueBag::from_fill(&|slot: fill::Slot| slot.fill_any(42u64)).to_shared();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::BigUnsigned(42)
));
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn fmt_to_owned() {
let debug = ValueBag::from_debug(&"a value").to_owned();
let display = ValueBag::from_display(&"a value").to_owned();
assert!(matches!(
debug.inner,
internal::owned::OwnedInternal::Debug(_)
));
assert!(matches!(
display.inner,
internal::owned::OwnedInternal::Display(_)
));
assert_eq!("\"a value\"", debug.to_string());
assert_eq!("a value", display.to_string());
let debug = debug.by_ref();
let display = display.by_ref();
assert!(matches!(debug.inner, internal::Internal::AnonDebug(_)));
assert!(matches!(display.inner, internal::Internal::AnonDisplay(_)));
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn fmt_to_shared() {
let debug = ValueBag::from_debug(&"a value").to_shared();
let display = ValueBag::from_display(&"a value").to_shared();
assert!(matches!(
debug.inner,
internal::owned::OwnedInternal::SharedDebug(_)
));
assert!(matches!(
display.inner,
internal::owned::OwnedInternal::SharedDisplay(_)
));
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn owned_fmt_to_owned() {
let debug = ValueBag::capture_shared_debug("a value".to_string()).to_owned();
let display = ValueBag::capture_shared_display("a value".to_string()).to_owned();
assert!(matches!(
debug.inner,
internal::owned::OwnedInternal::SharedDebug(_)
));
assert!(matches!(
display.inner,
internal::owned::OwnedInternal::SharedDisplay(_)
));
assert_eq!("\"a value\"", debug.to_string());
assert_eq!("a value", display.to_string());
let debug = debug.by_ref();
let display = display.by_ref();
assert!(matches!(debug.inner, internal::Internal::SharedRefDebug(_)));
assert!(matches!(
display.inner,
internal::Internal::SharedRefDisplay(_)
));
}
#[test]
#[cfg(feature = "error")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn error_to_owned() {
use crate::std::io;
let value =
ValueBag::from_dyn_error(&io::Error::new(io::ErrorKind::Other, "something failed!"))
.to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::Error(_)
));
let value = value.by_ref();
assert!(matches!(value.inner, internal::Internal::AnonError(_)));
assert!(value.to_borrowed_error().is_some());
}
#[test]
#[cfg(feature = "error")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn error_to_shared() {
use crate::std::io;
let value =
ValueBag::from_dyn_error(&io::Error::new(io::ErrorKind::Other, "something failed!"))
.to_shared();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedError(_)
));
}
#[test]
#[cfg(feature = "error")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn owned_error_to_owned() {
use crate::std::io;
let value = ValueBag::capture_shared_error(io::Error::new(
io::ErrorKind::Other,
"something failed!",
))
.to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedError(_)
));
let value = value.by_ref();
assert!(matches!(value.inner, internal::Internal::SharedRefError(_)));
}
#[test]
#[cfg(feature = "serde1")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn serde1_to_owned() {
let value = ValueBag::from_serde1(&42u64).to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::Serde1(_)
));
let value = value.by_ref();
assert!(matches!(value.inner, internal::Internal::AnonSerde1(_)));
}
#[test]
#[cfg(feature = "serde1")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn serde1_to_shared() {
let value = ValueBag::from_serde1(&42u64).to_shared();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedSerde1(_)
));
}
#[test]
#[cfg(feature = "serde1")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn owned_serde1_to_owned() {
let value = ValueBag::capture_shared_serde1("a value".to_string()).to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedSerde1(_)
));
let value = value.by_ref();
assert!(matches!(
value.inner,
internal::Internal::SharedRefSerde1(_)
));
}
#[test]
#[cfg(feature = "sval2")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn sval2_to_owned() {
let value = ValueBag::from_sval2(&42u64).to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::Sval2(_)
));
let value = value.by_ref();
assert!(matches!(value.inner, internal::Internal::AnonSval2(_)));
}
#[test]
#[cfg(feature = "sval2")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn sval2_to_shared() {
let value = ValueBag::from_sval2(&42u64).to_shared();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedSval2(_)
));
}
#[test]
#[cfg(feature = "sval2")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn owned_sval2_to_owned() {
let value = ValueBag::capture_shared_sval2("a value".to_string()).to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedSval2(_)
));
let value = value.by_ref();
assert!(matches!(value.inner, internal::Internal::SharedRefSval2(_)));
}
#[test]
#[cfg(feature = "seq")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn seq_to_owned() {
let value = ValueBag::from_seq_slice(&[1, 2, 3]).to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::Seq(_)
));
let value = value.by_ref();
assert!(matches!(value.inner, internal::Internal::AnonSeq(_)));
}
#[test]
#[cfg(feature = "seq")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn seq_to_shared() {
let value = ValueBag::from_seq_slice(&[1, 2, 3]).to_shared();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedSeq(_)
));
}
#[test]
#[cfg(feature = "seq")]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn owned_seq_to_owned() {
let value = ValueBag::capture_shared_seq_slice(vec![1, 2, 3]).to_owned();
assert!(matches!(
value.inner,
internal::owned::OwnedInternal::SharedSeq(_)
));
let value = value.by_ref();
assert!(matches!(value.inner, internal::Internal::SharedRefSeq(_)));
}
}