1use core::fmt;
4use std::fmt::Display;
5use std::io::{self, Read};
6use std::path::Path;
7use std::sync::Arc;
8
9use ecow::{EcoVec, eco_format};
10use tinymist_std::{ImmutBytes, ImmutPath};
11use typst::diag::{PackageError, PackageResult};
12use typst::syntax::package::{PackageSpec, VersionlessPackageSpec};
13
14#[cfg(feature = "fs-pack")]
15mod fs;
16#[cfg(feature = "gitcl-pack")]
17mod gitcl;
18#[cfg(feature = "http-pack")]
19mod http;
20mod memory;
21mod ops;
22#[cfg(feature = "release-pack")]
23mod release;
24mod tarball;
25#[cfg(feature = "universe-pack")]
26mod universe;
27
28#[cfg(feature = "fs-pack")]
29pub use fs::*;
30#[cfg(feature = "gitcl-pack")]
31pub use gitcl::*;
32#[cfg(feature = "http-pack")]
33pub use http::*;
34pub use memory::*;
35pub use ops::*;
36#[cfg(feature = "release-pack")]
37pub use release::*;
38pub use tarball::*;
39#[cfg(feature = "universe-pack")]
40pub use universe::*;
41
42pub enum PackFile<'a> {
44 Data(io::Cursor<ImmutBytes>),
46 Read(Box<dyn Read + 'a>),
48}
49
50impl io::Read for PackFile<'_> {
51 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
52 match self {
53 PackFile::Data(data) => data.read(buf),
54 PackFile::Read(reader) => reader.read(buf),
55 }
56 }
57}
58
59pub enum PackEntries<'a> {
61 Data(EcoVec<ImmutPath>),
63 Read(Box<dyn Iterator<Item = Path> + 'a>),
65}
66
67pub trait PackFs: fmt::Debug {
69 fn read_all(
71 &mut self,
72 f: &mut (dyn FnMut(&str, PackFile) -> PackageResult<()> + Send + Sync),
73 ) -> PackageResult<()>;
74 fn read(&self, _path: &str) -> io::Result<PackFile<'_>> {
76 Err(unsupported())
77 }
78 fn entries(&self) -> io::Result<PackEntries<'_>> {
80 Err(unsupported())
81 }
82}
83
84pub enum PackSpecifier {
86 Versioned(PackageSpec),
88 Versionless(VersionlessPackageSpec),
90}
91
92pub trait Pack: PackFs {}
94
95pub trait PackExt: Pack {
97 fn filter(&mut self, f: impl Fn(&str) -> bool + Send + Sync) -> impl Pack
99 where
100 Self: std::marker::Sized,
101 {
102 FilterPack { src: self, f }
103 }
104}
105
106pub trait CloneIntoPack: fmt::Debug {
108 fn clone_into_pack(&mut self, pack: &mut impl PackFs) -> std::io::Result<()>;
110}
111
112#[derive(Debug, Clone)]
114pub struct Package {
115 pub pack: Arc<dyn Pack + Send + Sync>,
117}
118
119fn unsupported() -> io::Error {
120 io::Error::new(io::ErrorKind::Unsupported, "unsupported operation")
121}
122
123fn malform(e: io::Error) -> PackageError {
124 PackageError::MalformedArchive(Some(eco_format!("{e:?}")))
125}
126
127fn other_io(e: impl Display) -> io::Error {
128 io::Error::other(e.to_string())
129}
130
131fn other(e: impl Display) -> PackageError {
132 PackageError::Other(Some(eco_format!("{e}")))
133}