use std::ops::Deref;
use std::sync::Arc;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
#[serde(untagged)] pub enum MaybeArc<T> {
NoArc(T),
Arc(Arc<T>),
}
impl<T> MaybeArc<T> {
#[inline]
pub fn arc(t: T) -> Self {
Self::Arc(Arc::new(t))
}
#[inline]
pub fn no_arc(t: T) -> Self {
Self::NoArc(t)
}
pub fn is_arc(&self) -> bool {
matches!(self, Self::Arc(..))
}
}
impl<T> AsRef<T> for MaybeArc<T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<T: Clone> MaybeArc<T> {
#[inline]
pub fn into_inner(self) -> T {
match self {
Self::Arc(a) => Arc::unwrap_or_clone(a),
Self::NoArc(a) => a,
}
}
}
impl<T: Clone> Clone for MaybeArc<T> {
fn clone(&self) -> Self {
match self {
Self::Arc(a) => Self::Arc(a.clone()),
Self::NoArc(a) => Self::NoArc(a.clone()),
}
}
}
impl<T> Deref for MaybeArc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
match self {
Self::Arc(a) => a,
Self::NoArc(a) => a,
}
}
}
impl<T, I> FromIterator<I> for MaybeArc<T>
where
T: FromIterator<I>,
{
fn from_iter<U: IntoIterator<Item = I>>(iter: U) -> Self {
let inner = T::from_iter(iter);
MaybeArc::NoArc(inner)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_serializing() {
let original = String::from("42");
let ma_original = MaybeArc::arc(original.clone());
let encoded = serde_json::to_string(&ma_original).unwrap();
let decoded: MaybeArc<String> = serde_json::from_str(&encoded).unwrap();
assert_eq!(decoded.as_ref(), &original);
assert!(!decoded.is_arc());
let decoded: String = serde_json::from_str(&encoded).unwrap();
assert_eq!(decoded, original);
}
#[test]
fn test_deserializing() {
let original = String::from("42");
let encoded = serde_json::to_string(&original).unwrap();
let decoded: MaybeArc<String> = serde_json::from_str(&encoded).unwrap();
assert_eq!(decoded.as_ref(), &original);
assert!(!decoded.is_arc());
}
}