Skip to main content

eth_avatars/
resource.rs

1use std::{str::FromStr, sync::Arc};
2
3use crate::{
4    FetchError, LocatorError,
5    Resource::Unresolved,
6    modules::{arweave::Arweave, ethereum::Ethereum, http::Http, ipfs::Ipfs, swarm::Swarm},
7};
8
9pub type Dyncoder = Arc<dyn Decoder>;
10
11pub trait Decoder: Send + Sync + 'static {
12    fn decode(&self, bytes: Vec<u8>) -> Result<Resource, FetchError>;
13}
14
15pub trait Locator: Sized + Send + Sync + 'static + FromStr<Err = LocatorError> + PartialEq {
16    fn of(resource: &Resource) -> Option<&Self>;
17}
18
19pub enum Resource {
20    Raw(Vec<u8>),
21    Unresolved(String),
22    Http(Http),
23    Ipfs(Ipfs),
24    Swarm(Swarm),
25    Arweave(Arweave),
26    Ethereum(Ethereum),
27    Decode {
28        source: Box<Resource>,
29        decoder: Dyncoder,
30    },
31}
32
33impl From<Vec<u8>> for Resource {
34    fn from(bytes: Vec<u8>) -> Self {
35        Self::Raw(bytes)
36    }
37}
38
39impl From<Http> for Resource {
40    fn from(http: Http) -> Self {
41        Self::Http(http)
42    }
43}
44
45impl From<Ipfs> for Resource {
46    fn from(ipfs: Ipfs) -> Self {
47        Self::Ipfs(ipfs)
48    }
49}
50
51impl From<Swarm> for Resource {
52    fn from(swarm: Swarm) -> Self {
53        Self::Swarm(swarm)
54    }
55}
56
57impl From<Arweave> for Resource {
58    fn from(arweave: Arweave) -> Self {
59        Self::Arweave(arweave)
60    }
61}
62
63impl From<Ethereum> for Resource {
64    fn from(ethereum: Ethereum) -> Self {
65        Self::Ethereum(ethereum)
66    }
67}
68
69impl FromStr for Resource {
70    type Err = LocatorError;
71
72    fn from_str(s: &str) -> Result<Self, Self::Err> {
73        let (schema, _) = s.split_once(':').ok_or(LocatorError::NoSchema)?;
74
75        match schema.to_lowercase().as_str() {
76            "ipfs" | "ipns" => s.parse().map(Resource::Ipfs),
77            "bzz" => s.parse().map(Resource::Swarm),
78            "ar" => s.parse().map(Resource::Arweave),
79            "eip155" => s.parse().map(Resource::Ethereum),
80            "http" | "https" => s.parse().map(Resource::Http),
81            // "data" => decode_data_uri(rest).map(Resource::Raw),
82            _ => Ok(Unresolved(s.to_string())),
83        }
84    }
85}
86
87impl Resource {
88    pub fn decoded_by(self, decoder: impl Decoder) -> Self {
89        Self::Decode {
90            source: Box::new(self),
91            decoder: Arc::new(decoder),
92        }
93    }
94}