use crate::store::ReadValue;
use crate::store::StorageError;
use crate::store::places::Taken;
use amethystate_core::failure::{Because, spelled};
use amethystate_core::path::{StorePath, StorePathError};
use error_stack::Report;
use std::fmt;
use std::sync::Arc;
pub enum OpenStruct {
Refused { at: StorePath, said: Arc<str> },
WillNotRead { at: StorePath, why: Because },
Taken(Box<Taken>),
NotAPath(StorePathError),
Store(Because),
}
impl OpenStruct {
pub fn explain(&self) -> String {
match self {
Self::Store(why) | Self::WillNotRead { why, .. } => why.explain(),
other => other.to_string(),
}
}
}
impl fmt::Display for OpenStruct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Refused { at, said } => {
write!(f, "a declared check refused what is stored at {at}: {said}")
}
Self::WillNotRead { at, .. } => {
write!(f, "what is stored at {at} will not read back")
}
Self::Taken(taken) => write!(f, "{taken}"),
Self::NotAPath(why) => write!(f, "the field was given no path to sit at: {why}"),
Self::Store(why) => write!(f, "{}", why.current_context()),
}
}
}
impl fmt::Debug for OpenStruct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
spelled(self, f)
}
}
impl std::error::Error for OpenStruct {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::NotAPath(why) => Some(why),
Self::Store(why) | Self::WillNotRead { why, .. } => {
why.caused().map(|under| under as &dyn std::error::Error)
}
Self::Refused { .. } | Self::Taken(_) => None,
}
}
}
impl From<Box<Taken>> for OpenStruct {
fn from(taken: Box<Taken>) -> Self {
Self::Taken(taken)
}
}
impl From<StorePathError> for OpenStruct {
fn from(why: StorePathError) -> Self {
Self::NotAPath(why)
}
}
impl From<Report<StorageError>> for OpenStruct {
fn from(why: Report<StorageError>) -> Self {
Self::Store(why.into())
}
}
impl From<ReadValue> for OpenStruct {
fn from(why: ReadValue) -> Self {
match why {
ReadValue::NotAPath(why) => Self::NotAPath(why),
ReadValue::WillNotRead { at, why } => Self::WillNotRead { at, why },
ReadValue::Store(why) => Self::Store(why),
ReadValue::Closed { at } => Self::Store(
Report::new(StorageError::Closed)
.attach(amethystate_core::facts::Key(at))
.into(),
),
}
}
}
impl From<amethystate_core::primitives::error::WriteValue> for OpenStruct {
fn from(why: amethystate_core::primitives::error::WriteValue) -> Self {
Self::Store(Report::<StorageError>::from(why).into())
}
}
impl From<OpenStruct> for Report<StorageError> {
fn from(why: OpenStruct) -> Self {
match why {
OpenStruct::Store(report) | OpenStruct::WillNotRead { why: report, .. } => {
report.into_report()
}
OpenStruct::NotAPath(why) => Report::new(why).change_context(StorageError::Path),
OpenStruct::Refused { at, said } => Report::new(StorageError::Read)
.attach(amethystate_core::facts::Key(at))
.attach(amethystate_core::facts::Refused(said.to_string())),
OpenStruct::Taken(taken) => crate::store::places::refused(&taken),
}
}
}
pub enum OpenStore {
WouldNotOpen { why: Because },
Migrating { why: Because },
Store(Because),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum WillNotOpen {
#[default]
Refuse,
StartFresh,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WhenItWillNotRead {
TryAgainFor(std::time::Duration),
SetAside,
Refuse,
Overwrite,
}
impl Default for WhenItWillNotRead {
fn default() -> Self {
Self::TryAgainFor(std::time::Duration::from_secs(5))
}
}
impl OpenStore {
pub fn from_store(why: Report<StorageError>) -> Self {
match *why.current_context() {
StorageError::Open => Self::WouldNotOpen { why: why.into() },
StorageError::Migrate => Self::Migrating { why: why.into() },
_ => Self::Store(why.into()),
}
}
pub fn explain(&self) -> String {
let (Self::WouldNotOpen { why } | Self::Migrating { why } | Self::Store(why)) = self;
why.explain()
}
}
impl fmt::Display for OpenStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::WouldNotOpen { .. } => f.write_str("the store would not open"),
Self::Migrating { .. } => f.write_str(
"the store opened, and the data would not come up to the declared schema",
),
Self::Store(why) => write!(f, "{}", why.current_context()),
}
}
}
impl fmt::Debug for OpenStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
spelled(self, f)
}
}
impl std::error::Error for OpenStore {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
let (Self::WouldNotOpen { why } | Self::Migrating { why } | Self::Store(why)) = self;
why.caused().map(|under| under as &dyn std::error::Error)
}
}
impl From<Report<StorageError>> for OpenStore {
fn from(why: Report<StorageError>) -> Self {
Self::from_store(why)
}
}
impl From<OpenStore> for Report<StorageError> {
fn from(why: OpenStore) -> Self {
let (OpenStore::WouldNotOpen { why }
| OpenStore::Migrating { why }
| OpenStore::Store(why)) = why;
why.into_report()
}
}