1use std::ops::Deref;
2use std::path::PathBuf;
3use url::Url;
4
5#[derive(Debug)]
6pub enum Imported {
7 Bytes(Vec<u8>),
8 File(PathBuf),
9}
10
11pub trait Backend {
34 type Error: Into<crate::Error>;
35
36 fn name(&self) -> &'static str;
37
38 fn is_available(&self) -> bool;
39 fn is_preferred_for(&self, path: &Url) -> Option<bool>;
40
41 fn import(&self, program: &Url) -> Result<Imported, Self::Error>;
42}
43
44#[repr(transparent)]
46struct Importer<B, E>(B)
47where
48 B: Backend<Error = E>;
49
50impl<B, E> Backend for Importer<B, E>
51where
52 B: Backend<Error = E>,
53 E: Into<crate::Error>,
54{
55 type Error = crate::Error;
56
57 fn name(&self) -> &'static str {
58 self.0.name()
59 }
60
61 fn is_available(&self) -> bool {
62 self.0.is_available()
63 }
64
65 fn is_preferred_for(&self, path: &Url) -> Option<bool> {
66 self.0.is_preferred_for(path)
67 }
68
69 fn import(&self, program: &Url) -> Result<Imported, Self::Error> {
70 self.0.import(program).map_err(|e| e.into())
71 }
72}
73
74#[repr(transparent)]
75pub struct DatabaseImporterBackend(Box<dyn Backend<Error = crate::Error>>);
76
77impl DatabaseImporterBackend {
78 pub fn new<B, E>(backend: B) -> Self
79 where
80 B: Backend<Error = E> + 'static,
81 E: Into<crate::Error> + 'static,
82 {
83 Self(Box::new(Importer(backend)))
84 }
85}
86
87impl Deref for DatabaseImporterBackend {
88 type Target = dyn Backend<Error=crate::Error>;
89
90 fn deref(&self) -> &Self::Target {
91 &*self.0
92 }
93}