use std::future::Future;
use fhir_model::for_all_versions;
use reqwest::StatusCode;
use serde::Serialize;
use super::{Client, Error};
use crate::{
extensions::{AnyResource, GenericResource},
version::{FhirVersion, fhir_version},
};
pub trait ResourceWrite<Version>: Serialize + Send + Sync {
fn update(
&mut self,
conditional: bool,
client: &Client<Version>,
) -> impl Future<Output = Result<bool, Error>> + Send;
fn create(
&mut self,
client: &Client<Version>,
) -> impl Future<Output = Result<String, Error>> + Send;
fn delete(self, client: &Client<Version>) -> impl Future<Output = Result<(), Error>> + Send;
}
impl<R, V> ResourceWrite<V> for R
where
R: AnyResource<V> + Serialize + Send + Sync,
V: FhirVersion,
(StatusCode, V::OperationOutcome): Into<Error>,
{
async fn update(&mut self, conditional: bool, client: &Client<V>) -> Result<bool, Error> {
let id = self.id().ok_or(Error::MissingId)?;
let version_id =
conditional.then(|| self.version_id().ok_or(Error::MissingVersionId)).transpose()?;
let (created, version_id) =
client.update_generic(R::TYPE_STR, id, self, version_id).await?;
self.set_version_id(version_id);
Ok(created)
}
async fn create(&mut self, client: &Client<V>) -> Result<String, Error> {
let (id, version_id) = client.create_generic(R::TYPE_STR, self).await?;
self.set_id(id.clone());
if let Some(version) = version_id {
self.set_version_id(version);
}
Ok(id)
}
async fn delete(self, client: &Client<V>) -> Result<(), Error> {
let id = self.id().ok_or(Error::MissingId)?;
client.delete(R::TYPE, id).await?;
Ok(())
}
}
pub trait AnyResourceWrite: Serialize + Send + Sync {
type Version: FhirVersion;
fn update(
&mut self,
conditional: bool,
client: &Client<Self::Version>,
) -> impl Future<Output = Result<bool, Error>> + Send;
fn create(
&mut self,
client: &Client<Self::Version>,
) -> impl Future<Output = Result<String, Error>> + Send;
fn delete(
self,
client: &Client<Self::Version>,
) -> impl Future<Output = Result<(), Error>> + Send;
}
macro_rules! impl_generic_resource_write {
($version:ident) => {
use fhir_model::$version;
impl AnyResourceWrite for $version::resources::Resource {
type Version = fhir_version!($version);
async fn update(
&mut self,
conditional: bool,
client: &Client<Self::Version>,
) -> Result<bool, Error> {
let id = self.as_base_resource().id().as_deref().ok_or(Error::MissingId)?;
let version_id = conditional
.then(|| self.version_id().ok_or(Error::MissingVersionId))
.transpose()?;
let (created, version_id) = client
.update_generic(self.resource_type().as_str(), id, self, version_id)
.await?;
self.set_version_id(version_id);
Ok(created)
}
async fn create(&mut self, client: &Client<Self::Version>) -> Result<String, Error> {
let (id, version_id) =
client.create_generic(self.resource_type().as_str(), self).await?;
self.as_base_resource_mut().set_id(Some(id.clone()));
if let Some(version) = version_id {
self.set_version_id(version);
}
Ok(id)
}
async fn delete(self, client: &Client<Self::Version>) -> Result<(), Error> {
let id = self.as_base_resource().id().as_deref().ok_or(Error::MissingId)?;
client.delete(self.resource_type(), id).await?;
Ok(())
}
}
};
}
for_all_versions!(impl_generic_resource_write);