use std::{fmt::Display, ops::Deref, sync::Arc};
use datasize::DataSize;
use serde::{Deserialize, Serialize};
#[derive(Clone, DataSize, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum SharedObject<T> {
Owned(Box<T>),
Shared(Arc<T>),
}
impl<T> Deref for SharedObject<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
match self {
SharedObject::Owned(obj) => obj,
SharedObject::Shared(shared) => shared,
}
}
}
impl<T> AsRef<[u8]> for SharedObject<T>
where
T: AsRef<[u8]>,
{
fn as_ref(&self) -> &[u8] {
match self {
SharedObject::Owned(obj) => <T as AsRef<[u8]>>::as_ref(obj),
SharedObject::Shared(shared) => <T as AsRef<[u8]>>::as_ref(shared),
}
}
}
impl<T> SharedObject<T> {
#[inline]
pub(crate) fn owned(inner: T) -> Self {
SharedObject::Owned(Box::new(inner))
}
pub(crate) fn shared(inner: Arc<T>) -> Self {
SharedObject::Shared(inner)
}
}
impl<T> Display for SharedObject<T>
where
T: Display,
{
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SharedObject::Owned(inner) => inner.fmt(f),
SharedObject::Shared(inner) => inner.fmt(f),
}
}
}
impl<T> Serialize for SharedObject<T>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
SharedObject::Owned(inner) => inner.serialize(serializer),
SharedObject::Shared(shared) => shared.serialize(serializer),
}
}
}
impl<'de, T> Deserialize<'de> for SharedObject<T>
where
T: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
T::deserialize(deserializer).map(SharedObject::owned)
}
}
#[cfg(test)]
mod tests {
use std::{io::Cursor, sync::Arc};
use serde::{de::DeserializeOwned, Serialize};
use crate::types::{Deploy, SharedObject};
impl<T> SharedObject<T>
where
T: Clone,
{
pub(crate) fn into_inner(self) -> T {
match self {
SharedObject::Owned(inner) => *inner,
SharedObject::Shared(shared) => (*shared).clone(),
}
}
}
#[inline]
fn serialize<T: Serialize>(value: &T) -> Vec<u8> {
rmp_serde::to_vec(value).expect("could not serialize value")
}
#[inline]
fn deserialize<T: DeserializeOwned>(raw: &[u8]) -> T {
rmp_serde::from_read(Cursor::new(raw)).expect("could not deserialize value")
}
#[test]
fn loaded_item_for_bytes_deserializes_like_bytevec() {
let mut rng = crate::new_rng();
let deploy = Deploy::random(&mut rng);
let payload = bincode::serialize(&deploy).expect("could not serialize deploy");
let loaded_item_owned = SharedObject::owned(payload.clone());
let loaded_item_shared = SharedObject::shared(Arc::new(payload.clone()));
let serialized = serialize(&payload);
assert_eq!(serialized, serialize(&loaded_item_owned));
assert_eq!(serialized, serialize(&loaded_item_shared));
let deserialized: SharedObject<Vec<u8>> = deserialize(&serialized);
assert_eq!(payload, deserialized.into_inner());
}
}