use std::sync::Arc;
pub struct ModelRef<D: ?Sized>(Inner<D>);
enum Inner<D: ?Sized> {
Model(Arc<D>),
Id(String),
}
impl<D: ?Sized> ModelRef<D> {
#[must_use]
pub fn from_arc(model: Arc<D>) -> Self {
Self(Inner::Model(model))
}
#[must_use]
pub fn from_id(id: impl Into<String>) -> Self {
Self(Inner::Id(id.into()))
}
#[must_use]
pub fn model(&self) -> Option<&Arc<D>> {
match &self.0 {
Inner::Model(model) => Some(model),
Inner::Id(_) => None,
}
}
#[must_use]
pub fn unresolved_id(&self) -> Option<&str> {
match &self.0 {
Inner::Model(_) => None,
Inner::Id(id) => Some(id),
}
}
#[must_use]
pub fn is_resolved(&self) -> bool {
matches!(self.0, Inner::Model(_))
}
pub fn into_model(self) -> Result<Arc<D>, String> {
match self.0 {
Inner::Model(model) => Ok(model),
Inner::Id(id) => Err(id),
}
}
}
impl<D: ?Sized> Clone for ModelRef<D> {
fn clone(&self) -> Self {
Self(match &self.0 {
Inner::Model(model) => Inner::Model(Arc::clone(model)),
Inner::Id(id) => Inner::Id(id.clone()),
})
}
}
impl<D: ?Sized> std::fmt::Debug for ModelRef<D> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.0 {
Inner::Model(_) => f.write_str("ModelRef::Model(..)"),
Inner::Id(id) => f.debug_tuple("ModelRef::Id").field(id).finish(),
}
}
}
impl<D: ?Sized> From<Arc<D>> for ModelRef<D> {
fn from(model: Arc<D>) -> Self {
Self::from_arc(model)
}
}
impl<D: ?Sized> From<String> for ModelRef<D> {
fn from(id: String) -> Self {
Self::from_id(id)
}
}
impl<D: ?Sized> From<&str> for ModelRef<D> {
fn from(id: &str) -> Self {
Self::from_id(id)
}
}
pub struct ServiceRef<D: ?Sized>(Arc<D>);
impl<D: ?Sized> ServiceRef<D> {
#[must_use]
pub fn from_arc(service: Arc<D>) -> Self {
Self(service)
}
#[must_use]
pub fn inner(&self) -> &Arc<D> {
&self.0
}
#[must_use]
pub fn into_inner(self) -> Arc<D> {
self.0
}
}
impl<D: ?Sized> Clone for ServiceRef<D> {
fn clone(&self) -> Self {
Self(Arc::clone(&self.0))
}
}
impl<D: ?Sized> std::fmt::Debug for ServiceRef<D> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("ServiceRef(..)")
}
}
impl<D: ?Sized> std::ops::Deref for ServiceRef<D> {
type Target = D;
fn deref(&self) -> &D {
&self.0
}
}
impl<D: ?Sized> From<Arc<D>> for ServiceRef<D> {
fn from(service: Arc<D>) -> Self {
Self::from_arc(service)
}
}
macro_rules! ref_conversions {
($alias:ident, $trait_:ident, $dyn_trait:ident) => {
impl<T: $trait_> From<T> for $alias {
fn from(model: T) -> Self {
Self::from_arc(::std::sync::Arc::new(model))
}
}
impl<T: $trait_> From<::std::sync::Arc<T>> for $alias {
fn from(model: ::std::sync::Arc<T>) -> Self {
Self::from_arc(model)
}
}
};
}
pub(crate) use ref_conversions;