use dioxus::core::Task;
pub trait AsyncState {
type Data;
type Error;
fn is_loading(&self) -> bool;
fn is_success(&self) -> bool;
fn is_error(&self) -> bool;
fn data(&self) -> Option<&Self::Data>;
fn error(&self) -> Option<&Self::Error>;
}
#[derive(Clone, PartialEq, Debug)]
pub enum State<T, E> {
Loading { task: Task },
Success(T),
Error(E),
}
impl<T, E> AsyncState for State<T, E> {
type Data = T;
type Error = E;
fn is_loading(&self) -> bool {
matches!(self, State::Loading { task: _ })
}
fn is_success(&self) -> bool {
matches!(self, State::Success(_))
}
fn is_error(&self) -> bool {
matches!(self, State::Error(_))
}
fn data(&self) -> Option<&T> {
match self {
State::Success(data) => Some(data),
_ => None,
}
}
fn error(&self) -> Option<&E> {
match self {
State::Error(error) => Some(error),
_ => None,
}
}
}
impl<T, E> State<T, E> {
pub fn is_loading(&self) -> bool {
<Self as AsyncState>::is_loading(self)
}
pub fn is_success(&self) -> bool {
<Self as AsyncState>::is_success(self)
}
pub fn is_error(&self) -> bool {
<Self as AsyncState>::is_error(self)
}
pub fn data(&self) -> Option<&T> {
<Self as AsyncState>::data(self)
}
pub fn error(&self) -> Option<&E> {
<Self as AsyncState>::error(self)
}
pub fn map<U, F>(self, op: F) -> State<U, E>
where
F: FnOnce(T) -> U,
{
match self {
State::Success(data) => State::Success(op(data)),
State::Error(e) => State::Error(e),
State::Loading { task } => State::Loading { task },
}
}
pub fn map_err<F, O>(self, op: O) -> State<T, F>
where
O: FnOnce(E) -> F,
{
match self {
State::Success(data) => State::Success(data),
State::Error(e) => State::Error(op(e)),
State::Loading { task } => State::Loading { task },
}
}
pub fn and_then<U, F>(self, op: F) -> State<U, E>
where
F: FnOnce(T) -> State<U, E>,
{
match self {
State::Success(data) => op(data),
State::Error(e) => State::Error(e),
State::Loading { task } => State::Loading { task },
}
}
}