read_url/tar/
tar_url.rs

1use super::{
2    super::{context::*, errors::*, url::*, util::*},
3    compression::*,
4};
5
6use {
7    relative_path::*,
8    std::{fmt, sync::*},
9};
10
11//
12// TarUrl
13//
14
15/// A URL for an entry in a tarball (tar archive).
16///
17/// Supports bare as well as compressed tarballs.
18///
19/// The URL scheme is "tar:", followed by full archive URL, a `!`, and then the entry path
20/// within the archive. The fragment of the archive URL is used to explicitly set the
21/// compression algorithm. If the compression is not explicitly set, will attempt to determine
22/// it according to the format of the archive URL.
23#[derive(Clone, Debug)]
24pub struct TarUrl {
25    /// The archive [URL].
26    pub archive_url: Arc<UrlRef>,
27
28    /// The entry path.
29    pub path: RelativePathBuf,
30
31    /// Compression.
32    pub compression: Option<TarCompression>,
33
34    pub(crate) context: UrlContextRef,
35}
36
37impl TarUrl {
38    /// Parse.
39    pub fn parse(url_representation: &str) -> Result<(String, String), UrlError> {
40        parse_archive_entry_url_representation(url_representation, "tar")
41    }
42
43    /// Compression from archive URL fragment.
44    pub fn compression_from(archive_url: &UrlRef) -> Result<Option<TarCompression>, UrlError> {
45        Ok(match archive_url.fragment() {
46            Some(fragment) => Some(fragment.parse()?),
47            None => None,
48        })
49    }
50
51    /// Constructor.
52    pub fn new(
53        context: &UrlContextRef,
54        archive_url: Arc<UrlRef>,
55        path: RelativePathBuf,
56        compression: Option<TarCompression>,
57    ) -> Self {
58        Self { archive_url, path, compression, context: context.clone() }
59    }
60
61    /// Constructor.
62    pub fn new_with(&self, path: RelativePathBuf) -> TarUrl {
63        Self::new(&self.context, self.archive_url.clone(), path, self.compression.clone())
64    }
65
66    #[cfg(any(feature = "blocking", feature = "async"))]
67    pub(crate) fn get_compression(&self) -> TarCompression {
68        match &self.compression {
69            Some(compression) => compression.clone(),
70
71            None => match self.archive_url.format() {
72                Some(archive_format) => match archive_format.as_str() {
73                    "tar.gz" => TarCompression::Gzip,
74                    "tar.zstd" => TarCompression::Zstandard,
75                    _ => TarCompression::None,
76                },
77
78                _ => TarCompression::None,
79            },
80        }
81    }
82}
83
84impl fmt::Display for TarUrl {
85    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
86        write!(formatter, "tar:{}!{}", self.archive_url, self.path)
87    }
88}
89
90// Conversions
91
92impl Into<UrlRef> for TarUrl {
93    fn into(self) -> UrlRef {
94        Box::new(self)
95    }
96}