#[derive(Debug, Default, Clone, Hash)]
pub struct AlruError {
msg: heapless::Vec<u8, 128>,
}
#[cfg(feature = "derive")]
pub mod derive {
pub use crate::alrulab_macros::CloneValued;
}
impl AlruError {
#[inline]
#[must_use]
pub fn new(msg: &str) -> AlruError {
if msg.len() > 128 {
panic!("msg to long");
}
AlruError { msg: heapless::Vec::from_slice(msg.as_bytes()).unwrap_or_default() }
}
#[inline]
#[must_use]
pub fn from_utf8(msg: &[u8]) -> AlruError {
match core::str::from_utf8(msg) {
Ok(_) => AlruError { msg: heapless::Vec::from_slice(msg).unwrap_or_default() },
Err(_) => AlruError { msg: heapless::Vec::from_slice("An Error was detected".as_bytes()).unwrap_or_default() },
}
}
#[inline]
pub unsafe fn from_utf8_unchecked(msg: &[u8]) -> AlruError {
AlruError { msg: heapless::Vec::from_slice(msg).unwrap_or_default() }
}
pub fn as_bytes(&self) -> &[u8] {
&self.msg
}
pub fn as_mut_bytes(&mut self) -> &mut [u8] {
&mut self.msg
}
pub fn as_str(&self) -> &str {
core::str::from_utf8(self.as_bytes()).unwrap_or("An Error was detected")
}
pub fn as_mut_str(&mut self) -> &mut str {
core::str::from_utf8_mut(self.as_mut_bytes()).unwrap_or_default()
}
pub fn default(&self) -> &str {
let str = "An Error was detected";
let bytes = str.as_bytes();
core::str::from_utf8(bytes).unwrap_or("An Error was detected")
}
}
impl core::fmt::Display for AlruError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl core::error::Error for AlruError {
fn description(&self) -> &str {
self.as_str()
}
fn cause(&self) -> Option<&dyn core::error::Error> {
None
}
}
#[derive(Debug, Clone, Hash)]
pub enum Value<T> {
Okay(T),
Error(AlruError),
}
impl<T: Default> Value<T> {
#[inline]
#[must_use]
pub const fn new_okay(value: T) -> Value<T> {
Value::Okay(value)
}
#[inline]
#[must_use]
pub const fn new_error(error: AlruError) -> Value<T> {
Value::Error(error)
}
#[inline]
#[must_use]
pub const fn nok(value: T) -> Value<T> {
Value::new_okay(value)
}
#[inline]
#[must_use]
pub const fn nerr(error: AlruError) -> Value<T> {
Value::new_error(error)
}
#[inline]
pub fn is_ok(&self) -> bool {
matches!(self, Value::Okay(_))
}
#[inline]
pub fn is_err(&self) -> bool {
matches!(self, Value::Error(_))
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn into_result(self) -> Result<T, AlruError> {
match self {
Value::Okay(val) => Ok(val),
Value::Error(err) => Err(err),
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap(self) -> T {
match self {
Value::Okay(val) => val,
Value::Error(err) => panic!("{}", err),
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap_err(self) -> AlruError {
match self {
Value::Okay(_) => panic!("value is ok"),
Value::Error(err) => err,
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap_or(self, default: T) -> T {
match self {
Value::Okay(val) => val,
Value::Error(_) => default,
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap_err_or(self, default: AlruError) -> AlruError {
match self {
Value::Okay(_) => panic!("value is ok"),
Value::Error(err) => err,
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap_or_else(self, default: impl FnOnce() -> T) -> T {
match self {
Value::Okay(val) => val,
Value::Error(_) => default(),
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap_err_or_else(self, default: impl FnOnce() -> AlruError) -> AlruError {
match self {
Value::Okay(_) => panic!("value is ok"),
Value::Error(err) => err,
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap_or_default(self) -> T {
match self {
Value::Okay(val) => val,
Value::Error(_) => Default::default(),
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn unwrap_err_or_default(self) -> AlruError {
match self {
Value::Okay(_) => Default::default(),
Value::Error(err) => err,
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn expect(self, msg: &str) -> T {
match self {
Value::Okay(val) => val,
Value::Error(err) => panic!("paniced: {} = Out: {}", msg, err),
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Value<U> {
match self {
Value::Okay(val) => Value::Okay(f(val)),
Value::Error(err) => Value::Error(err),
}
}
#[inline]
#[must_use = "self will be dropped, if the result is not using"]
pub fn map_err(self, f: impl FnOnce(AlruError) -> AlruError) -> Value<T> {
match self {
Value::Okay(val) => Value::Okay(val),
Value::Error(err) => Value::Error(f(err)),
}
}
}
impl<T> core::ops::Try for Value<T> {
type Output = T;
type Residual = Value<core::convert::Infallible>;
fn from_output(output: Self::Output) -> Self {
Value::Okay(output)
}
fn branch(self) -> core::ops::ControlFlow<Self::Residual, Self::Output> {
match self {
Value::Okay(val) => core::ops::ControlFlow::Continue(val),
Value::Error(err) => core::ops::ControlFlow::Break(Value::Error(err)),
}
}
}
impl<T> core::ops::FromResidual<Value<core::convert::Infallible>> for Value<T> {
fn from_residual(residual: Value<core::convert::Infallible>) -> Self {
match residual {
Value::Okay(_) => unreachable!(),
Value::Error(err) => Value::Error(err),
}
}
}
pub trait CloneValued {
fn clone_to_valued(&self) -> Value<Self>
where
Self: Sized;
fn clone_from_valued(&mut self, value: Value<Self>)
where
Self: Sized;
}
pub trait AsValued<T> {
fn as_valued(&self) -> Value<T>
where
Self: Sized;
}