Skip to main content

wvb_tauri/
config.rs

1use std::collections::HashMap;
2use std::path::PathBuf;
3use tauri::path::BaseDirectory;
4use tauri::{AppHandle, Manager, Runtime};
5use wvb::remote;
6
7pub use wvb::remote::HttpConfig as Http;
8
9type DynamicDirFn<R> = fn(app: &AppHandle<R>) -> Result<PathBuf, Box<dyn std::error::Error>>;
10
11#[derive(Clone)]
12pub(crate) enum Dir<R: Runtime> {
13  Static(String),
14  Dynamic(DynamicDirFn<R>),
15}
16
17impl<R: Runtime> Dir<R> {
18  pub fn resolve(&self, app: &AppHandle<R>) -> Result<PathBuf, Box<dyn std::error::Error>> {
19    match self {
20      Self::Static(dir) => Ok(PathBuf::from(dir)),
21      Self::Dynamic(f) => {
22        let dir = f(app)?;
23        Ok(dir)
24      }
25    }
26  }
27}
28
29#[derive(Clone, Default)]
30pub struct Source<R: Runtime> {
31  pub(crate) builtin_dir: Option<Dir<R>>,
32  pub(crate) remote_dir: Option<Dir<R>>,
33}
34
35impl<R: Runtime> Source<R> {
36  pub fn new() -> Self {
37    Self {
38      builtin_dir: None,
39      remote_dir: None,
40    }
41  }
42
43  pub fn builtin_dir<T: Into<String>>(mut self, dir: T) -> Self {
44    self.builtin_dir = Some(Dir::Static(dir.into()));
45    self
46  }
47
48  pub fn builtin_dir_fn(mut self, dir: DynamicDirFn<R>) -> Self {
49    self.builtin_dir = Some(Dir::Dynamic(dir));
50    self
51  }
52
53  pub fn remote_dir<T: Into<String>>(mut self, dir: T) -> Self {
54    self.remote_dir = Some(Dir::Static(dir.into()));
55    self
56  }
57
58  pub fn remote_dir_fn(mut self, dir: DynamicDirFn<R>) -> Self {
59    self.remote_dir = Some(Dir::Dynamic(dir));
60    self
61  }
62
63  pub(crate) fn resolve_builtin_dir(&self, app: &AppHandle<R>) -> crate::Result<PathBuf> {
64    let dir = match self.builtin_dir {
65      Some(ref builtin_dir) => {
66        let dir = builtin_dir
67          .resolve(app)
68          .map_err(|e| crate::Error::FailToResolveDirectory(e.to_string()))?;
69        dir
70      }
71      None => {
72        let dir = app.path().resolve("bundles", BaseDirectory::Resource)?;
73        dir
74      }
75    };
76    Ok(dir)
77  }
78
79  pub(crate) fn resolve_remote_dir(&self, app: &AppHandle<R>) -> crate::Result<PathBuf> {
80    let dir = match self.remote_dir {
81      Some(ref remote_dir) => {
82        let dir = remote_dir
83          .resolve(app)
84          .map_err(|e| crate::Error::FailToResolveDirectory(e.to_string()))?;
85        dir
86      }
87      None => {
88        let dir = app.path().resolve("bundles", BaseDirectory::Resource)?;
89        dir
90      }
91    };
92    Ok(dir)
93  }
94}
95
96#[derive(Clone, Default)]
97pub struct Remote {
98  builder: remote::RemoteBuilder,
99}
100
101impl Remote {
102  pub fn new(endpoint: impl Into<String>) -> Self {
103    let builder = remote::Remote::builder().endpoint(endpoint);
104    Self { builder }
105  }
106
107  pub fn http(mut self, http: Http) -> Self {
108    self.builder = self.builder.http(http);
109    self
110  }
111
112  pub fn on_download<F>(mut self, on_download: F) -> Self
113  where
114    F: Fn(u64, u64, String) + Send + Sync + 'static,
115  {
116    self.builder = self.builder.on_download(on_download);
117    self
118  }
119
120  pub(crate) fn build(self) -> crate::Result<remote::Remote> {
121    let remote = self.builder.build()?;
122    Ok(remote)
123  }
124}
125
126#[derive(Clone)]
127pub struct BundleProtocolConfig {
128  scheme: String,
129}
130
131impl BundleProtocolConfig {
132  pub fn new<S: Into<String>>(scheme: S) -> Self {
133    Self {
134      scheme: scheme.into(),
135    }
136  }
137}
138
139#[derive(Clone)]
140pub struct LocalProtocolConfig {
141  scheme: String,
142  pub(crate) hosts: HashMap<String, String>,
143}
144
145impl LocalProtocolConfig {
146  pub fn new<S: Into<String>>(scheme: S) -> Self {
147    Self {
148      scheme: scheme.into(),
149      hosts: HashMap::new(),
150    }
151  }
152
153  pub fn new_with_hosts<T: Into<HashMap<String, String>>>(scheme: String, hosts: T) -> Self {
154    Self {
155      scheme,
156      hosts: hosts.into(),
157    }
158  }
159
160  pub fn host<T: Into<String>, U: Into<String>>(mut self, host: T, url: U) -> Self {
161    self.hosts.insert(host.into(), url.into());
162    self
163  }
164
165  pub fn hosts<T: Into<HashMap<String, String>>>(mut self, hosts: T) -> Self {
166    self.hosts = hosts.into();
167    self
168  }
169}
170
171#[derive(Clone)]
172pub enum Protocol {
173  Bundle(BundleProtocolConfig),
174  Local(LocalProtocolConfig),
175}
176
177impl Protocol {
178  pub fn bundle<S: Into<String>>(scheme: S) -> BundleProtocolConfig {
179    BundleProtocolConfig::new(scheme)
180  }
181
182  pub fn local<S: Into<String>>(scheme: S) -> LocalProtocolConfig {
183    LocalProtocolConfig::new(scheme)
184  }
185
186  pub fn scheme(&self) -> &str {
187    match self {
188      Protocol::Bundle(x) => &x.scheme,
189      Protocol::Local(x) => &x.scheme,
190    }
191  }
192}
193
194impl From<BundleProtocolConfig> for Protocol {
195  fn from(value: BundleProtocolConfig) -> Self {
196    Protocol::Bundle(value)
197  }
198}
199
200impl From<LocalProtocolConfig> for Protocol {
201  fn from(value: LocalProtocolConfig) -> Self {
202    Protocol::Local(value)
203  }
204}
205
206#[derive(Clone, Default)]
207pub struct Config<R: Runtime> {
208  pub(crate) source: Source<R>,
209  pub(crate) protocols: Vec<Protocol>,
210  pub(crate) remote: Option<Remote>,
211}
212
213impl<R: Runtime> Config<R> {
214  pub fn new() -> Self {
215    Self {
216      source: Source::new(),
217      protocols: vec![],
218      remote: Default::default(),
219    }
220  }
221
222  pub fn source(mut self, source: Source<R>) -> Self {
223    self.source = source;
224    self
225  }
226
227  pub fn protocol<P: Into<Protocol>>(mut self, protocol: P) -> Self {
228    self.protocols.push(protocol.into());
229    self
230  }
231
232  pub fn remote(mut self, remote: Remote) -> Self {
233    self.remote = Some(remote);
234    self
235  }
236
237  pub(crate) fn build_remote(&self) -> crate::Result<Option<remote::Remote>> {
238    if let Some(ref remote_config) = self.remote {
239      let remote = remote_config.clone().build()?;
240      Ok(Some(remote))
241    } else {
242      Ok(None)
243    }
244  }
245}