tinymist_package/pack/
http.rs1use ecow::eco_format;
2use typst::diag::PackageError;
3
4use super::*;
5use crate::registry::threaded_http;
6
7#[derive(Clone)]
9pub struct HttpPack<S> {
10    pub specifier: PackageSpec,
12    pub url: S,
14}
15
16impl<S: AsRef<str>> HttpPack<S> {
17    pub fn new(specifier: PackageSpec, url: S) -> Self {
19        Self { specifier, url }
20    }
21}
22
23impl<S: AsRef<str>> fmt::Debug for HttpPack<S> {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(f, "HttpPack({})", self.url.as_ref())
26    }
27}
28
29impl<S: AsRef<str>> PackFs for HttpPack<S> {
30    fn read_all(
31        &mut self,
32        f: &mut (dyn FnMut(&str, PackFile) -> PackageResult<()> + Send + Sync),
33    ) -> PackageResult<()> {
34        let spec = &self.specifier;
35        let url = self.url.as_ref();
36        threaded_http(url, None, |resp| {
37            let reader = match resp.and_then(|r| r.error_for_status()) {
38                Ok(response) => response,
39                Err(err) if matches!(err.status().map(|s| s.as_u16()), Some(404)) => {
40                    return Err(PackageError::NotFound(spec.clone()));
41                }
42                Err(err) => return Err(PackageError::NetworkFailed(Some(eco_format!("{err}")))),
43            };
44
45            let decompressed = flate2::read::GzDecoder::new(reader);
46            let mut tarbar = TarballPack::new(decompressed);
47
48            tarbar.read_all(f)
55        })
56        .ok_or_else(|| PackageError::Other(Some(eco_format!("cannot spawn http thread"))))?
57    }
58}
59
60impl<S: AsRef<str>> Pack for HttpPack<S> {}
61impl<P: AsRef<str>> PackExt for HttpPack<P> {}