use std::{
fmt::{Debug, Display},
str::FromStr,
};
use fhir_model::for_all_versions;
use serde::{Serialize, de::DeserializeOwned};
use super::{GenericResource, SearchEntryModeExt};
pub trait BundleExt {
type Entry: BundleEntryExt
+ Serialize
+ DeserializeOwned
+ Debug
+ Clone
+ PartialEq
+ Unpin
+ Send
+ Sync;
fn next_page_url(&self) -> Option<&String>;
fn total(&self) -> Option<u32>;
fn entries(&self) -> impl Iterator<Item = &Self::Entry> + Send;
fn take_entries(&mut self) -> Vec<Option<Self::Entry>>;
fn into_entries(self) -> impl Iterator<Item = Self::Entry> + Send + 'static;
fn make_batch(entries: Vec<Option<Self::Entry>>) -> Self;
fn make_transaction(entries: Vec<Option<Self::Entry>>) -> Self;
}
macro_rules! impl_bundle_ext {
($version:ident) => {
mod $version {
use fhir_model::$version::{
codes::BundleType,
resources::{Bundle, BundleEntry},
};
use super::*;
impl BundleExt for Bundle {
type Entry = BundleEntry;
fn next_page_url(&self) -> Option<&String> {
Bundle::next_page_url(self)
}
fn total(&self) -> Option<u32> {
self.total
}
fn entries(&self) -> impl Iterator<Item = &Self::Entry> + Send {
self.0.entry.iter().flatten()
}
fn take_entries(&mut self) -> Vec<Option<Self::Entry>> {
std::mem::take(&mut self.0.entry)
}
fn into_entries(self) -> impl Iterator<Item = Self::Entry> + Send + 'static {
self.0.entry.into_iter().flatten()
}
fn make_batch(entries: Vec<Option<Self::Entry>>) -> Self {
#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
Self::builder().r#type(BundleType::Batch).entry(entries).build().unwrap()
}
fn make_transaction(entries: Vec<Option<Self::Entry>>) -> Self {
#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
Self::builder().r#type(BundleType::Transaction).entry(entries).build().unwrap()
}
}
}
};
}
#[cfg(feature = "builders")]
mod bundle_ext {
use super::*;
for_all_versions!(impl_bundle_ext);
}
pub trait BundleEntryExt {
type Resource: GenericResource
+ Serialize
+ DeserializeOwned
+ Debug
+ Clone
+ PartialEq
+ Unpin
+ Send
+ Sync;
type Request: BundleEntryRequestExt
+ Serialize
+ DeserializeOwned
+ Debug
+ Clone
+ PartialEq
+ Unpin
+ Send
+ Sync;
type SearchEntryMode: SearchEntryModeExt
+ Serialize
+ DeserializeOwned
+ Debug
+ FromStr
+ AsRef<str>
+ Display
+ Clone
+ Copy
+ PartialEq
+ Eq
+ Unpin
+ Send
+ Sync;
fn search_mode(&self) -> Option<&Self::SearchEntryMode>;
fn full_url(&self) -> Option<&String>;
fn request(&self) -> Option<&Self::Request>;
fn resource(&self) -> Option<&Self::Resource>;
fn into_resource(self) -> Option<Self::Resource>;
fn empty() -> Self;
fn with_full_url(self, full_url: String) -> Self;
fn with_request(self, request: Self::Request) -> Self;
fn with_resource(self, resource: Self::Resource) -> Self;
}
macro_rules! impl_bundle_entry_ext {
($version:ident) => {
mod $version {
use fhir_model::$version::{
codes::SearchEntryMode,
resources::{BundleEntry, BundleEntryRequest, Resource},
};
use super::*;
impl BundleEntryExt for BundleEntry {
type Resource = Resource;
type Request = BundleEntryRequest;
type SearchEntryMode = SearchEntryMode;
fn search_mode(&self) -> Option<&Self::SearchEntryMode> {
self.search.as_ref().and_then(|search| search.mode.as_ref())
}
fn full_url(&self) -> Option<&String> {
self.full_url.as_ref()
}
fn request(&self) -> Option<&Self::Request> {
self.request.as_ref()
}
fn resource(&self) -> Option<&Self::Resource> {
self.resource.as_ref()
}
fn into_resource(self) -> Option<Self::Resource> {
self.resource
}
fn empty() -> Self {
#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
Self::builder().build().unwrap()
}
fn with_full_url(mut self, full_url: String) -> Self {
self.full_url = Some(full_url);
self
}
fn with_request(mut self, request: Self::Request) -> Self {
self.request = Some(request);
self
}
fn with_resource(mut self, resource: Self::Resource) -> Self {
self.resource = Some(resource);
self
}
}
}
};
}
#[cfg(feature = "builders")]
mod bundle_entry_ext {
use super::*;
for_all_versions!(impl_bundle_entry_ext);
}
pub trait BundleEntryRequestExt {
fn is_delete(&self) -> bool;
fn make_post(url: String) -> Self;
fn make_put(url: String) -> Self;
fn make_get(url: String) -> Self;
fn make_delete(url: String) -> Self;
fn with_if_match(self, if_match: String) -> Self;
}
macro_rules! impl_bundle_entry_request_ext {
($version:ident) => {
mod $version {
use fhir_model::$version::{codes::HTTPVerb, resources::BundleEntryRequest};
use super::*;
impl BundleEntryRequestExt for BundleEntryRequest {
fn is_delete(&self) -> bool {
self.method == HTTPVerb::Delete
}
fn make_post(url: String) -> Self {
#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
Self::builder().url(url).method(HTTPVerb::Post).build().unwrap()
}
fn make_put(url: String) -> Self {
#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
Self::builder().url(url).method(HTTPVerb::Put).build().unwrap()
}
fn make_get(url: String) -> Self {
#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
Self::builder().url(url).method(HTTPVerb::Get).build().unwrap()
}
fn make_delete(url: String) -> Self {
#[allow(clippy::unwrap_used, reason = "We know the builder succeeds")]
Self::builder().url(url).method(HTTPVerb::Delete).build().unwrap()
}
fn with_if_match(mut self, if_match: String) -> Self {
self.if_match = Some(if_match);
self
}
}
}
};
}
#[cfg(feature = "builders")]
mod bundle_entry_request_ext {
use super::*;
for_all_versions!(impl_bundle_entry_request_ext);
}