Skip to main content

vertigo/fetch/
resource.rs

1use std::rc::Rc;
2
3use crate::{Computed, ToComputed};
4
5/// The state of the resource.
6#[derive(Clone, Debug)]
7pub enum Resource<T> {
8    Loading,
9    Ready(T),
10    Error(String),
11}
12
13pub enum ResourceError {
14    Loading,
15    Error(String),
16}
17
18impl<T> From<ResourceError> for Resource<T> {
19    fn from(residual: ResourceError) -> Resource<T> {
20        match residual {
21            ResourceError::Error(message) => Resource::Error(message),
22            ResourceError::Loading => Resource::Loading,
23        }
24    }
25}
26
27impl<T> Resource<T> {
28    /// Convert into a `Result` so that `?` can be used inside functions
29    /// returning another `Resource`. Use `resource.into_result()?` instead
30    /// of the previously-required nightly `Try` impl.
31    pub fn into_result(self) -> Result<T, ResourceError> {
32        match self {
33            Resource::Ready(value) => Ok(value),
34            Resource::Loading => Err(ResourceError::Loading),
35            Resource::Error(message) => Err(ResourceError::Error(message)),
36        }
37    }
38}
39
40impl<T> Resource<T> {
41    pub fn map<K>(self, map: impl Fn(T) -> K) -> Resource<K> {
42        match self {
43            Resource::Loading => Resource::Loading,
44            Resource::Ready(data) => Resource::Ready(map(data)),
45            Resource::Error(err) => Resource::Error(err),
46        }
47    }
48
49    pub fn ref_map<K>(&self, map: impl Fn(&T) -> K) -> Resource<K> {
50        match self {
51            Resource::Loading => Resource::Loading,
52            Resource::Ready(data) => Resource::Ready(map(data)),
53            Resource::Error(err) => Resource::Error(err.clone()),
54        }
55    }
56}
57
58impl<T: Clone> Resource<T> {
59    #[must_use]
60    pub fn ref_clone(&self) -> Self {
61        match self {
62            Resource::Loading => Resource::Loading,
63            Resource::Ready(data) => Resource::Ready(data.clone()),
64            Resource::Error(error) => Resource::Error(error.clone()),
65        }
66    }
67}
68
69impl<T: PartialEq> PartialEq for Resource<T> {
70    fn eq(&self, other: &Self) -> bool {
71        match (self, other) {
72            (Resource::Loading, Resource::Loading) => true,
73            (Resource::Error(message1), Resource::Error(message2)) => message1.eq(message2),
74            (Resource::Ready(val1), Resource::Ready(val2)) => val1.eq(val2),
75            _ => false,
76        }
77    }
78}
79
80impl<T: Clone + 'static> ToComputed<Resource<Rc<T>>> for Resource<T> {
81    fn to_computed(&self) -> crate::Computed<Resource<Rc<T>>> {
82        Computed::from({
83            let myself = self.clone();
84            move |_| myself.clone().map(|item| Rc::new(item))
85        })
86    }
87}
88
89impl<T: Clone + 'static> ToComputed<Resource<Rc<T>>> for Computed<Resource<T>> {
90    fn to_computed(&self) -> crate::Computed<Resource<Rc<T>>> {
91        self.map(|res| res.map(|item| Rc::new(item)))
92    }
93}