use camino::Utf8PathBuf;
use compact_str::{CompactString, ToCompactString};
use serde::{Deserialize, Serialize};
use std::{error::Error, fmt::Display, process::{ExitCode, Termination}, time::Instant};
#[derive(Deserialize, Serialize, PartialEq, PartialOrd, Ord, Eq, Debug, Clone)]
#[non_exhaustive]
pub enum Catastrophe {
Error {
description: CompactString,
source: Option<Box<Catastrophe>>,
},
}
unsafe impl Send for Catastrophe {}
unsafe impl Sync for Catastrophe {}
impl Catastrophe {
pub fn new_error(description: CompactString, source: Option<Box<Catastrophe>>) -> Self {
Self::Error{description, source}
}
pub fn g<S: AsRef<str>>(description: S) -> Self {
Self::new_error(description.as_ref().to_compact_string(), None)
}
pub fn description(&self) -> CompactString {
match self {
Catastrophe::Error { description, source } => {
match source {
Some(inner) => inner.to_string().into(),
None => description.clone(),
}
}
}
}
}
impl<E: Error> From<E> for Catastrophe {
fn from(value: E) -> Self {
let source = value.source().map(|er| Box::new(Catastrophe::from(er)));
let description = value.to_compact_string();
Self::new_error(description, source)
}
}
impl From<Catastrophe> for Box<dyn Error + Send + Sync> {
fn from(value: Catastrophe) -> Self {
match value {
Catastrophe::Error { description, .. } => {
Box::<dyn Error + Send + Sync>::from(description.to_string())
},
}
}
}
impl From<Catastrophe> for ExitCode {
fn from(value: Catastrophe) -> Self {
match value {
Catastrophe::Error { description: _, source: _ } => Self::FAILURE,
}
}
}
impl Termination for Catastrophe {
fn report(self) -> ExitCode {
self.into()
}
}
impl Display for Catastrophe {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Catastrophe::Error { description, source } => {
match source {
Some(c) => {
write!(f, "{}", c.description())
}
None => {
write!(f, "{}", description)
}
}
}
}
}
}
pub struct ErrCode(u16);
impl ErrCode {
pub fn new(n: u16) -> Self {
Self(n)
}
pub fn from_hex_str<S: AsRef<str>>(s: S) -> Res<Self> {
let hex = u16::from_str_radix(s.as_ref(), 16)?;
Ok(Self::new(hex))
}
pub fn unknown_error() -> Self {
Self::new(u16::MAX)
}
}
impl<E: Error> From<E> for ErrCode {
fn from(_: E) -> Self {
Self::unknown_error()
}
}
pub type Empty = ();
pub type Res<T> = Result<T, Catastrophe>;
pub type ResE = Res<Empty>;
pub type Maybe<T> = Option<T>;
#[derive(Clone, PartialEq, PartialOrd, Default)]
pub struct Optional<D: Default>(D);
#[derive(Clone, PartialEq, PartialOrd, Hash)]
pub struct Isfet {
instant: Instant,
explanation: CompactString,
child: Option<Box<Self>>,
}
impl Isfet {
pub fn new(instant: Instant, explanation: CompactString, child: Option<Box<Self>>) -> Self {
Self {
instant,
explanation,
child,
}
}
pub fn to_vec(self) -> Vec<Self> {
let mut out = vec![self.clone()];
let mut rest: Vec<_> = self.into_iter().collect();
out.append(&mut rest);
out
}
}
impl Display for Isfet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(child) = &self.child {
write!(f, "{:#?}|{}\n{}", self.instant, self.explanation, child)
} else {
write!(f, "{:#?}|{}", self.instant, self.explanation)
}
}
}
impl Iterator for Isfet {
type Item = Self;
fn next(&mut self) -> Option<Self::Item> {
if let Some(n) = &self.child {
let c = n.clone();
Some(*c)
} else {
None
}
}
}
impl<E: Error> From<E> for Isfet {
fn from(value: E) -> Self {
let instant = Instant::now();
if let Some(child_err) = value.source() {
let child: Isfet = child_err.into();
Isfet::new(instant, value.to_compact_string(), Some(Box::new(child)))
} else {
Isfet::new(instant, value.to_compact_string(), None)
}
}
}