dioxus_provider/
state.rs

1//! State: Async state enum for dioxus-provider
2//!
3//! This module provides the `State` enum and the `AsyncState` trait for working
4//! with asynchronous operations in dioxus-provider.
5
6use dioxus::core::Task;
7
8/// Common trait for async state types that represent loading, success, and error states
9///
10/// This trait provides a unified interface for working with different async state types
11/// in dioxus-provider, such as `State` and `MutationState`.
12pub trait AsyncState {
13    /// The type of successful data
14    type Data;
15    /// The type of error
16    type Error;
17
18    /// Returns true if the state is currently loading
19    fn is_loading(&self) -> bool;
20
21    /// Returns true if the state contains successful data
22    fn is_success(&self) -> bool;
23
24    /// Returns true if the state contains an error
25    fn is_error(&self) -> bool;
26
27    /// Returns the data if successful, None otherwise
28    fn data(&self) -> Option<&Self::Data>;
29
30    /// Returns the error if failed, None otherwise
31    fn error(&self) -> Option<&Self::Error>;
32}
33
34/// Represents the state of an async operation
35#[derive(Clone, PartialEq, Debug)]
36pub enum State<T, E> {
37    /// The operation is currently loading
38    Loading { task: Task },
39    /// The operation completed successfully with data
40    Success(T),
41    /// The operation failed with an error
42    Error(E),
43}
44
45impl<T, E> AsyncState for State<T, E> {
46    type Data = T;
47    type Error = E;
48
49    fn is_loading(&self) -> bool {
50        matches!(self, State::Loading { task: _ })
51    }
52
53    fn is_success(&self) -> bool {
54        matches!(self, State::Success(_))
55    }
56
57    fn is_error(&self) -> bool {
58        matches!(self, State::Error(_))
59    }
60
61    fn data(&self) -> Option<&T> {
62        match self {
63            State::Success(data) => Some(data),
64            _ => None,
65        }
66    }
67
68    fn error(&self) -> Option<&E> {
69        match self {
70            State::Error(error) => Some(error),
71            _ => None,
72        }
73    }
74}
75
76impl<T, E> State<T, E> {
77    /// Returns true if the state is currently loading
78    pub fn is_loading(&self) -> bool {
79        <Self as AsyncState>::is_loading(self)
80    }
81
82    /// Returns true if the state contains successful data
83    pub fn is_success(&self) -> bool {
84        <Self as AsyncState>::is_success(self)
85    }
86
87    /// Returns true if the state contains an error
88    pub fn is_error(&self) -> bool {
89        <Self as AsyncState>::is_error(self)
90    }
91
92    /// Returns the data if successful, None otherwise
93    pub fn data(&self) -> Option<&T> {
94        <Self as AsyncState>::data(self)
95    }
96
97    /// Returns the error if failed, None otherwise
98    pub fn error(&self) -> Option<&E> {
99        <Self as AsyncState>::error(self)
100    }
101
102    /// Maps a State<T, E> to State<U, E> by applying a function to the contained data if successful.
103    pub fn map<U, F>(self, op: F) -> State<U, E>
104    where
105        F: FnOnce(T) -> U,
106    {
107        match self {
108            State::Success(data) => State::Success(op(data)),
109            State::Error(e) => State::Error(e),
110            State::Loading { task } => State::Loading { task },
111        }
112    }
113
114    /// Maps a State<T, E> to State<T, F> by applying a function to the contained error if failed.
115    pub fn map_err<F, O>(self, op: O) -> State<T, F>
116    where
117        O: FnOnce(E) -> F,
118    {
119        match self {
120            State::Success(data) => State::Success(data),
121            State::Error(e) => State::Error(op(e)),
122            State::Loading { task } => State::Loading { task },
123        }
124    }
125
126    /// Chains a State<T, E> to State<U, E> by applying a function to the contained data if successful.
127    pub fn and_then<U, F>(self, op: F) -> State<U, E>
128    where
129        F: FnOnce(T) -> State<U, E>,
130    {
131        match self {
132            State::Success(data) => op(data),
133            State::Error(e) => State::Error(e),
134            State::Loading { task } => State::Loading { task },
135        }
136    }
137}