Skip to main content

guinea_core/
load.rs

1use std::sync::Arc;
2
3/// Status of a value that arrives asynchronously (a feature's `State` field
4/// fed by a loader or a live push), so "not here yet" is representable as
5/// data instead of requiring a separate suspense mechanism at the read site.
6#[derive(Clone, Debug)]
7pub enum Load<T> {
8    NotAsked,
9    Loading,
10    Ready(T),
11    Failed(Arc<anyhow::Error>),
12}
13
14impl<T> Default for Load<T> {
15    fn default() -> Self {
16        Load::Loading
17    }
18}
19
20/// `anyhow::Error` has no equality of its own; two `Failed`s compare by
21/// `Arc` identity (a re-fetched failure is a *new* value and must re-render).
22impl<T: PartialEq> PartialEq for Load<T> {
23    fn eq(&self, other: &Self) -> bool {
24        match (self, other) {
25            (Load::NotAsked, Load::NotAsked) | (Load::Loading, Load::Loading) => true,
26            (Load::Ready(a), Load::Ready(b)) => a == b,
27            (Load::Failed(a), Load::Failed(b)) => Arc::ptr_eq(a, b),
28            _ => false,
29        }
30    }
31}
32
33impl<T: Eq> Eq for Load<T> {}
34
35impl<T> Load<T> {
36    pub fn failed(err: impl Into<anyhow::Error>) -> Self {
37        Load::Failed(Arc::new(err.into()))
38    }
39
40    pub fn ready(&self) -> Option<&T> {
41        match self {
42            Load::Ready(value) => Some(value),
43            _ => None,
44        }
45    }
46
47    pub fn is_loading(&self) -> bool {
48        matches!(self, Load::Loading)
49    }
50
51    pub fn error(&self) -> Option<&anyhow::Error> {
52        match self {
53            Load::Failed(err) => Some(err),
54            _ => None,
55        }
56    }
57}