use crate::store::StorageError;
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 ReadValue {
NotAPath(StorePathError),
WillNotRead { at: StorePath, why: Because },
Closed { at: StorePath },
Store(Because),
}
impl ReadValue {
pub fn from_store(at: &StorePath, why: Report<StorageError>) -> Self {
if *why.current_context() == StorageError::Closed {
return Self::Closed { at: at.clone() };
}
match crate::store::rules::will_not_read(&why) {
true => Self::WillNotRead {
at: at.clone(),
why: why.into(),
},
false => Self::Store(why.into()),
}
}
pub fn explain(&self) -> String {
match self {
Self::Store(why) | Self::WillNotRead { why, .. } => why.explain(),
other => other.to_string(),
}
}
}
impl fmt::Display for ReadValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotAPath(why) => write!(f, "the read was given no path to look at: {why}"),
Self::WillNotRead { at, .. } => {
write!(f, "what is stored at {at} will not read back")
}
Self::Closed { at } => write!(f, "the store was closed, so {at} was not read"),
Self::Store(why) => write!(f, "{}", why.current_context()),
}
}
}
impl fmt::Debug for ReadValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
spelled(self, f)
}
}
impl std::error::Error for ReadValue {
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::Closed { .. } => None,
}
}
}
impl From<StorePathError> for ReadValue {
fn from(why: StorePathError) -> Self {
Self::NotAPath(why)
}
}
impl From<Report<StorageError>> for ReadValue {
fn from(why: Report<StorageError>) -> Self {
Self::Store(why.into())
}
}
impl From<ReadValue> for Report<StorageError> {
fn from(why: ReadValue) -> Self {
match why {
ReadValue::Store(report) | ReadValue::WillNotRead { why: report, .. } => {
report.into_report()
}
ReadValue::NotAPath(why) => Report::new(why).change_context(StorageError::Path),
ReadValue::Closed { at } => {
Report::new(StorageError::Closed).attach(amethystate_core::facts::Key(at))
}
}
}
}
pub enum ScanKeys {
NotAPath(StorePathError),
KeyWillNotRead { under: StorePath, why: Because },
Closed { under: StorePath },
Store(Because),
}
impl ScanKeys {
pub fn from_store(under: &StorePath, why: Report<StorageError>) -> Self {
match *why.current_context() {
StorageError::Path => Self::KeyWillNotRead {
under: under.clone(),
why: why.into(),
},
StorageError::Closed => Self::Closed {
under: under.clone(),
},
_ => Self::Store(why.into()),
}
}
pub fn explain(&self) -> String {
match self {
Self::Store(why) | Self::KeyWillNotRead { why, .. } => why.explain(),
other => other.to_string(),
}
}
}
impl fmt::Display for ScanKeys {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotAPath(why) => write!(f, "the scan was given no prefix to list: {why}"),
Self::KeyWillNotRead { under, .. } => {
write!(f, "a key stored under {under} will not read back as a path")
}
Self::Closed { under } => {
write!(f, "the store was closed, so {under} was not listed")
}
Self::Store(why) => write!(f, "{}", why.current_context()),
}
}
}
impl fmt::Debug for ScanKeys {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
spelled(self, f)
}
}
impl std::error::Error for ScanKeys {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::NotAPath(why) => Some(why),
Self::Store(why) | Self::KeyWillNotRead { why, .. } => {
why.caused().map(|under| under as &dyn std::error::Error)
}
Self::Closed { .. } => None,
}
}
}
impl From<StorePathError> for ScanKeys {
fn from(why: StorePathError) -> Self {
Self::NotAPath(why)
}
}
impl From<Report<StorageError>> for ScanKeys {
fn from(why: Report<StorageError>) -> Self {
Self::Store(why.into())
}
}
impl From<ScanKeys> for Report<StorageError> {
fn from(why: ScanKeys) -> Self {
match why {
ScanKeys::Store(report) | ScanKeys::KeyWillNotRead { why: report, .. } => {
report.into_report()
}
ScanKeys::NotAPath(why) => Report::new(why).change_context(StorageError::Path),
ScanKeys::Closed { under } => {
Report::new(StorageError::Closed).attach(amethystate_core::facts::Prefix(under))
}
}
}
}
pub type ReadResult<T> = Result<T, ReadValue>;
pub type ScanResult<T> = Result<T, ScanKeys>;
pub enum LoadMap {
NotAPath(StorePathError),
Taken(Box<crate::store::places::Taken>),
KeyIsNotAnEntry {
under: StorePath,
stored: Arc<str>,
said: Arc<str>,
},
KeyWillNotRead {
under: StorePath,
entry: Arc<str>,
wanted: &'static str,
},
EntryWillNotRead { at: StorePath, why: Because },
Closed { under: StorePath },
Store(Because),
}
impl LoadMap {
pub fn from_store(at: &StorePath, why: Report<StorageError>) -> Self {
if *why.current_context() == StorageError::Closed {
return Self::Closed { under: at.clone() };
}
match crate::store::rules::will_not_read(&why) {
true => Self::EntryWillNotRead {
at: at.clone(),
why: why.into(),
},
false => Self::Store(why.into()),
}
}
pub fn explain(&self) -> String {
match self {
Self::Store(why) | Self::EntryWillNotRead { why, .. } => why.explain(),
other => other.to_string(),
}
}
}
impl fmt::Display for LoadMap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotAPath(why) => write!(f, "the map was given no path to sit at: {why}"),
Self::Taken(taken) => write!(f, "{taken}"),
Self::KeyIsNotAnEntry {
under,
stored,
said,
} => write!(f, "`{stored}` is not an entry of {under}: {said}"),
Self::KeyWillNotRead {
under,
entry,
wanted,
} => write!(f, "`{entry}` under {under} will not read as a {wanted}"),
Self::EntryWillNotRead { at, .. } => {
write!(f, "the entry at {at} will not read back")
}
Self::Closed { under } => {
write!(f, "the store was closed, so {under} was not read")
}
Self::Store(why) => write!(f, "{}", why.current_context()),
}
}
}
impl fmt::Debug for LoadMap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
spelled(self, f)
}
}
impl std::error::Error for LoadMap {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::NotAPath(why) => Some(why),
Self::Store(why) | Self::EntryWillNotRead { why, .. } => {
why.caused().map(|under| under as &dyn std::error::Error)
}
Self::Taken(_)
| Self::KeyIsNotAnEntry { .. }
| Self::KeyWillNotRead { .. }
| Self::Closed { .. } => None,
}
}
}
impl From<StorePathError> for LoadMap {
fn from(why: StorePathError) -> Self {
Self::NotAPath(why)
}
}
impl From<Report<StorageError>> for LoadMap {
fn from(why: Report<StorageError>) -> Self {
Self::Store(why.into())
}
}
impl From<Box<crate::store::places::Taken>> for LoadMap {
fn from(taken: Box<crate::store::places::Taken>) -> Self {
Self::Taken(taken)
}
}
impl From<amethystate_core::primitives::error::WriteValue> for LoadMap {
fn from(why: amethystate_core::primitives::error::WriteValue) -> Self {
Self::Store(Report::<StorageError>::from(why).into())
}
}
impl From<LoadMap> for Report<StorageError> {
fn from(why: LoadMap) -> Self {
match why {
LoadMap::Store(report) | LoadMap::EntryWillNotRead { why: report, .. } => {
report.into_report()
}
LoadMap::NotAPath(why) => Report::new(why).change_context(StorageError::Path),
LoadMap::Taken(taken) => crate::store::places::refused(&taken),
LoadMap::KeyIsNotAnEntry {
under,
stored,
said,
} => Report::new(StorageError::Path)
.attach(amethystate_core::facts::Prefix(under))
.attach(amethystate_core::facts::RawKey(stored.to_string()))
.attach(said.to_string()),
LoadMap::KeyWillNotRead {
under,
entry,
wanted,
} => Report::new(StorageError::Codec)
.attach(amethystate_core::facts::Prefix(under))
.attach(amethystate_core::facts::Entry(entry.to_string()))
.attach(format!("key type: {wanted}")),
LoadMap::Closed { under } => {
Report::new(StorageError::Closed).attach(amethystate_core::facts::Prefix(under))
}
}
}
}
impl From<LoadMap> for crate::store::OpenStruct {
fn from(why: LoadMap) -> Self {
match why {
LoadMap::NotAPath(why) => Self::NotAPath(why),
LoadMap::Taken(taken) => Self::Taken(taken),
LoadMap::EntryWillNotRead { at, why } => Self::WillNotRead { at, why },
other => Self::Store(Report::<StorageError>::from(other).into()),
}
}
}
pub type LoadMapResult<T> = Result<T, LoadMap>;