dioxus_provider/
provider_state.rs

1//! ProviderState: Async state enum for dioxus-provider
2//!
3//! This module provides the `ProviderState` 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 `ProviderState` 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 ProviderState<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 ProviderState<T, E> {
46    type Data = T;
47    type Error = E;
48
49    fn is_loading(&self) -> bool {
50        matches!(self, ProviderState::Loading { task: _ })
51    }
52
53    fn is_success(&self) -> bool {
54        matches!(self, ProviderState::Success(_))
55    }
56
57    fn is_error(&self) -> bool {
58        matches!(self, ProviderState::Error(_))
59    }
60
61    fn data(&self) -> Option<&T> {
62        match self {
63            ProviderState::Success(data) => Some(data),
64            _ => None,
65        }
66    }
67
68    fn error(&self) -> Option<&E> {
69        match self {
70            ProviderState::Error(error) => Some(error),
71            _ => None,
72        }
73    }
74}
75
76impl<T, E> ProviderState<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 ProviderState<T, E> to ProviderState<U, E> by applying a function to the contained data if successful.
103    pub fn map<U, F>(self, op: F) -> ProviderState<U, E>
104    where
105        F: FnOnce(T) -> U,
106    {
107        match self {
108            ProviderState::Success(data) => ProviderState::Success(op(data)),
109            ProviderState::Error(e) => ProviderState::Error(e),
110            ProviderState::Loading { task } => ProviderState::Loading { task },
111        }
112    }
113
114    /// Maps a ProviderState<T, E> to ProviderState<T, F> by applying a function to the contained error if failed.
115    pub fn map_err<F, O>(self, op: O) -> ProviderState<T, F>
116    where
117        O: FnOnce(E) -> F,
118    {
119        match self {
120            ProviderState::Success(data) => ProviderState::Success(data),
121            ProviderState::Error(e) => ProviderState::Error(op(e)),
122            ProviderState::Loading { task } => ProviderState::Loading { task },
123        }
124    }
125
126    /// Chains a ProviderState<T, E> to ProviderState<U, E> by applying a function to the contained data if successful.
127    pub fn and_then<U, F>(self, op: F) -> ProviderState<U, E>
128    where
129        F: FnOnce(T) -> ProviderState<U, E>,
130    {
131        match self {
132            ProviderState::Success(data) => op(data),
133            ProviderState::Error(e) => ProviderState::Error(e),
134            ProviderState::Loading { task } => ProviderState::Loading { task },
135        }
136    }
137}