use core::{fmt::Debug, ops::Deref, pin::Pin};
use crate::{
as_cpp_string::AsCppString,
container::{Container, RefContainer},
wrapper::{CppException, SandiaDecayDataBase},
};
pub struct GenericUninitDatabase<C: Container<Inner = SandiaDecayDataBase>>(C);
#[cfg(feature = "alloc")]
pub type UninitDatabase =
GenericUninitDatabase<crate::container::BoxContainer<SandiaDecayDataBase>>;
#[cfg(feature = "alloc")]
pub type UninitSharedDatabase =
GenericUninitDatabase<crate::container::ArcContainer<SandiaDecayDataBase>>;
pub type UninitLocalDatabase<'l> = GenericUninitDatabase<RefContainer<'l, SandiaDecayDataBase>>;
impl<C: Container<Inner = SandiaDecayDataBase>> Debug for GenericUninitDatabase<C> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("UninintDatabase")
}
}
impl<C: Container<Inner = SandiaDecayDataBase>> Default for GenericUninitDatabase<C>
where
C::Allocator: Default,
{
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<C: Container<Inner = SandiaDecayDataBase>> GenericUninitDatabase<C> {
#[inline]
pub fn new_in(allocator: C::Allocator) -> Self {
Self(SandiaDecayDataBase::new(allocator))
}
#[inline]
pub fn new() -> Self
where
C::Allocator: Default,
{
Self(SandiaDecayDataBase::new(C::Allocator::default()))
}
fn get_mut(&mut self) -> Pin<&mut SandiaDecayDataBase> {
self.0
.try_inner()
.expect("Uninit database should not be in a shared container")
}
pub fn init(
mut self,
path: impl AsCppString,
) -> Result<GenericDatabase<C>, (GenericUninitDatabase<C>, CppException)> {
match self.get_mut().init_path(path) {
Ok(()) => Ok(GenericDatabase(self.0)),
Err(exception) => Err((self, exception)),
}
}
pub fn init_bytes(
mut self,
bytes: impl AsRef<[u8]>,
) -> Result<GenericDatabase<C>, (GenericUninitDatabase<C>, CppException)> {
match self.get_mut().init_bytes(bytes) {
Ok(()) => Ok(GenericDatabase(self.0)),
Err(exception) => Err((self, exception)),
}
}
}
#[derive(Debug, Error)]
pub enum EnvInitError {
#[error("No `SANDIA_DATABASE_PATH` variable in the environment")]
NoEnvVar,
#[error(transparent)]
Exception(CppException),
}
impl<C: Container<Inner = SandiaDecayDataBase>> GenericUninitDatabase<C> {
#[cfg(feature = "std")]
#[inline]
pub fn init_env(self) -> Result<GenericDatabase<C>, (GenericUninitDatabase<C>, EnvInitError)> {
let Some(env_path) = std::env::var_os("SANDIA_DATABASE_PATH") else {
return Err((self, EnvInitError::NoEnvVar));
};
self.init(env_path)
.map_err(|(uninit, exception)| (uninit, EnvInitError::Exception(exception)))
}
}
impl<C: Container<Inner = SandiaDecayDataBase>> GenericUninitDatabase<C> {
#[cfg(feature = "database")]
#[inline]
pub fn init_vendor(self) -> GenericDatabase<C> {
self.init_bytes(sdecay_sys::database::DATABASE)
.expect("Embedded database should be valid")
}
#[cfg(feature = "database-min")]
#[inline]
pub fn init_vendor_min(self) -> GenericDatabase<C> {
self.init_bytes(sdecay_sys::database::DATABASE_MIN)
.expect("Embedded database should be valid")
}
#[cfg(feature = "database-nocoinc-min")]
#[inline]
pub fn init_vendor_nocoinc_min(self) -> GenericDatabase<C> {
self.init_bytes(sdecay_sys::database::DATABASE_NOCOINC_MIN)
.expect("Embedded database should be valid")
}
}
#[derive(Debug, Clone)]
pub struct GenericDatabase<C: Container<Inner = SandiaDecayDataBase>>(C);
#[cfg(feature = "alloc")]
pub type Database = GenericDatabase<crate::container::BoxContainer<SandiaDecayDataBase>>;
#[cfg(feature = "alloc")]
pub type SharedDatabase = GenericDatabase<crate::container::ArcContainer<SandiaDecayDataBase>>;
pub type LocalDatabase<'l> = GenericDatabase<RefContainer<'l, SandiaDecayDataBase>>;
impl<C: Container<Inner = SandiaDecayDataBase>> GenericDatabase<C> {
#[inline]
pub fn from_path_in(
allocator: C::Allocator,
path: impl AsCppString,
) -> Result<Self, CppException> {
match GenericUninitDatabase::new_in(allocator).init(path) {
Ok(init) => Ok(init),
Err((_, error)) => Err(error),
}
}
#[inline]
pub fn from_path(path: impl AsCppString) -> Result<Self, CppException>
where
C::Allocator: Default,
{
Self::from_path_in(C::Allocator::default(), path)
}
#[inline]
pub fn from_bytes_in(
allocator: C::Allocator,
bytes: impl AsRef<[u8]>,
) -> Result<Self, CppException> {
match GenericUninitDatabase::new_in(allocator).init_bytes(bytes) {
Ok(init) => Ok(init),
Err((_, error)) => Err(error),
}
}
#[inline]
pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, CppException>
where
C::Allocator: Default,
{
Self::from_bytes_in(C::Allocator::default(), bytes)
}
#[cfg(feature = "std")]
#[inline]
pub fn from_env_in(allocator: C::Allocator) -> Result<Self, EnvInitError> {
match GenericUninitDatabase::new_in(allocator).init_env() {
Ok(init) => Ok(init),
Err((_, error)) => Err(error),
}
}
#[cfg(feature = "std")]
#[inline]
pub fn from_env() -> Result<Self, EnvInitError>
where
C::Allocator: Default,
{
Self::from_env_in(C::Allocator::default())
}
#[cfg(feature = "database")]
#[inline]
pub fn vendor_in(allocator: C::Allocator) -> Self {
GenericUninitDatabase::new_in(allocator).init_vendor()
}
#[cfg(feature = "database")]
#[inline]
pub fn vendor() -> Self
where
C::Allocator: Default,
{
Self::vendor_in(C::Allocator::default())
}
#[cfg(feature = "database-min")]
#[inline]
pub fn vendor_min_in(allocator: C::Allocator) -> Self {
GenericUninitDatabase::new_in(allocator).init_vendor_min()
}
#[cfg(feature = "database-min")]
#[inline]
pub fn vendor_min() -> Self
where
C::Allocator: Default,
{
Self::vendor_min_in(C::Allocator::default())
}
#[cfg(feature = "database-nocoinc-min")]
#[inline]
pub fn vendor_nocoinc_min_in(allocator: C::Allocator) -> Self {
GenericUninitDatabase::new_in(allocator).init_vendor_nocoinc_min()
}
#[cfg(feature = "database-nocoinc-min")]
#[inline]
pub fn vendor_nocoinc_min() -> Self
where
C::Allocator: Default,
{
Self::vendor_nocoinc_min_in(C::Allocator::default())
}
#[inline]
pub fn reset(mut self) -> Result<GenericUninitDatabase<C>, Self> {
let Some(pin) = self.0.try_inner() else {
return Err(self);
};
pin.reset();
Ok(GenericUninitDatabase(self.0))
}
}
impl<C: Container<Inner = SandiaDecayDataBase>> Deref for GenericDatabase<C> {
type Target = SandiaDecayDataBase;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}