use super::{Actor, Object}; use crate::{config::Data, error::Error}; use async_trait::async_trait; use chrono::{DateTime, Utc}; use either::Either; use serde::{Deserialize, Serialize}; use std::fmt::Debug; use url::Url; #[doc(hidden)] #[derive(Serialize, Deserialize)] #[serde(untagged)] pub enum UntaggedEither { Left(L), Right(R), } #[async_trait] impl Object for Either where T: Object + Object + Send + Sync, R: Object + Object + Send + Sync, ::Kind: Send + Sync, ::Kind: Send + Sync, D: Sync + Send + Clone, E: From + Debug, { type DataType = D; type Kind = UntaggedEither; type Error = E; /// `id` field of the object fn id(&self) -> Url { match self { Either::Left(l) => l.id(), Either::Right(r) => r.id(), } } fn last_refreshed_at(&self) -> Option> { match self { Either::Left(l) => l.last_refreshed_at(), Either::Right(r) => r.last_refreshed_at(), } } async fn read_from_id( object_id: Url, data: &Data, ) -> Result, Self::Error> { let l = T::read_from_id(object_id.clone(), data).await?; if let Some(l) = l { return Ok(Some(Either::Left(l))); } let r = R::read_from_id(object_id.clone(), data).await?; if let Some(r) = r { return Ok(Some(Either::Right(r))); } Ok(None) } async fn delete(&self, data: &Data) -> Result<(), Self::Error> { match self { Either::Left(l) => l.delete(data).await, Either::Right(r) => r.delete(data).await, } } fn is_deleted(&self) -> bool { match self { Either::Left(l) => l.is_deleted(), Either::Right(r) => r.is_deleted(), } } async fn into_json(self, data: &Data) -> Result { Ok(match self { Either::Left(l) => UntaggedEither::Left(l.into_json(data).await?), Either::Right(r) => UntaggedEither::Right(r.into_json(data).await?), }) } async fn verify( json: &Self::Kind, expected_domain: &Url, data: &Data, ) -> Result<(), Self::Error> { match json { UntaggedEither::Left(l) => T::verify(l, expected_domain, data).await?, UntaggedEither::Right(r) => R::verify(r, expected_domain, data).await?, }; Ok(()) } async fn from_json(json: Self::Kind, data: &Data) -> Result { Ok(match json { UntaggedEither::Left(l) => Either::Left(T::from_json(l, data).await?), UntaggedEither::Right(r) => Either::Right(R::from_json(r, data).await?), }) } } #[async_trait] impl Actor for Either where T: Actor + Object + Object + Send + Sync + 'static, R: Actor + Object + Object + Send + Sync + 'static, ::Kind: Send + Sync, ::Kind: Send + Sync, D: Sync + Send + Clone, E: From + Debug, { fn public_key_pem(&self) -> &str { match self { Either::Left(l) => l.public_key_pem(), Either::Right(r) => r.public_key_pem(), } } fn private_key_pem(&self) -> Option { match self { Either::Left(l) => l.private_key_pem(), Either::Right(r) => r.private_key_pem(), } } fn inbox(&self) -> Url { match self { Either::Left(l) => l.inbox(), Either::Right(r) => r.inbox(), } } }