1use std::borrow::Cow;
2#[cfg(feature = "tar")]
3use std::fs::File;
4#[cfg(feature = "zstd")]
5use std::io::BufReader;
6use std::io::Read;
7use std::path::Path;
8
9#[cfg(feature = "bzip2")]
10use bzip2::read::BzDecoder as BzSysDecoder;
11#[cfg(feature = "bzip2-rs")]
12use bzip2_rs::decoder::DecoderReader as BzNativeDecoder;
13#[cfg(feature = "flate2")]
14use flate2::read::GzDecoder;
15#[cfg(feature = "lz4")]
16use lz4::Decoder as Lz4Decoder;
17#[cfg(feature = "xz2")]
18use xz2::read::XzDecoder;
19#[cfg(feature = "zstd")]
20use zstd::stream::read::Decoder as ZstdDecoder;
21
22use crate::Result;
23
24#[non_exhaustive]
27pub enum Entry<'a> {
28 #[cfg(feature = "tar")]
29 #[doc(hidden)]
30 Tar(tar::Entry<'a, File>),
31
32 #[cfg(all(feature = "bzip2", feature = "tar"))]
33 #[doc(hidden)]
34 TarBzip2(tar::Entry<'a, BzSysDecoder<File>>),
35
36 #[cfg(all(feature = "bzip2-rs", feature = "tar"))]
37 #[doc(hidden)]
38 TarBzip2Rs(tar::Entry<'a, BzNativeDecoder<File>>),
39
40 #[cfg(all(feature = "flate2", feature = "tar"))]
41 #[doc(hidden)]
42 TarGzip(tar::Entry<'a, GzDecoder<File>>),
43
44 #[cfg(all(feature = "lz4", feature = "tar"))]
45 #[doc(hidden)]
46 TarLz4(tar::Entry<'a, Lz4Decoder<File>>),
47
48 #[cfg(all(feature = "xz2", feature = "tar"))]
49 #[doc(hidden)]
50 TarXz(tar::Entry<'a, XzDecoder<File>>),
51
52 #[cfg(all(feature = "zstd", feature = "tar"))]
53 #[doc(hidden)]
54 TarZstd(tar::Entry<'a, ZstdDecoder<'static, BufReader<File>>>),
55
56 #[cfg(not(feature = "tar"))]
57 #[doc(hidden)]
58 __Phantom(std::marker::PhantomData<&'a str>),
59}
60
61impl<'a> Entry<'a> {
62 pub fn entry_type(&self) -> EntryType {
64 match self {
65 #[cfg(feature = "tar")]
66 Self::Tar(entry) => entry.header().entry_type().into(),
67
68 #[cfg(all(feature = "bzip2", feature = "tar"))]
69 Self::TarBzip2(entry) => entry.header().entry_type().into(),
70
71 #[cfg(all(feature = "bzip2-rs", feature = "tar"))]
72 Self::TarBzip2Rs(entry) => entry.header().entry_type().into(),
73
74 #[cfg(all(feature = "flate2", feature = "tar"))]
75 Self::TarGzip(entry) => entry.header().entry_type().into(),
76
77 #[cfg(all(feature = "lz4", feature = "tar"))]
78 Self::TarLz4(entry) => entry.header().entry_type().into(),
79
80 #[cfg(all(feature = "xz2", feature = "tar"))]
81 Self::TarXz(entry) => entry.header().entry_type().into(),
82
83 #[cfg(all(feature = "zstd", feature = "tar"))]
84 Self::TarZstd(entry) => entry.header().entry_type().into(),
85 }
86 }
87
88 #[must_use]
90 pub fn size(&self) -> u64 {
91 match self {
92 #[cfg(feature = "tar")]
93 Self::Tar(entry) => entry.size(),
94
95 #[cfg(all(feature = "bzip2", feature = "tar"))]
96 Self::TarBzip2(entry) => entry.size(),
97
98 #[cfg(all(feature = "bzip2-rs", feature = "tar"))]
99 Self::TarBzip2Rs(entry) => entry.size(),
100
101 #[cfg(all(feature = "flate2", feature = "tar"))]
102 Self::TarGzip(entry) => entry.size(),
103
104 #[cfg(all(feature = "lz4", feature = "tar"))]
105 Self::TarLz4(entry) => entry.size(),
106
107 #[cfg(all(feature = "xz2", feature = "tar"))]
108 Self::TarXz(entry) => entry.size(),
109
110 #[cfg(all(feature = "zstd", feature = "tar"))]
111 Self::TarZstd(entry) => entry.size(),
112 }
113 }
114
115 pub fn path(&self) -> Result<Cow<Path>> {
121 match self {
122 #[cfg(feature = "tar")]
123 Self::Tar(entry) => entry.path().map_err(From::from),
124
125 #[cfg(all(feature = "bzip2", feature = "tar"))]
126 Self::TarBzip2(entry) => entry.path().map_err(From::from),
127
128 #[cfg(all(feature = "bzip2-rs", feature = "tar"))]
129 Self::TarBzip2Rs(entry) => entry.path().map_err(From::from),
130
131 #[cfg(all(feature = "flate2", feature = "tar"))]
132 Self::TarGzip(entry) => entry.path().map_err(From::from),
133
134 #[cfg(all(feature = "lz4", feature = "tar"))]
135 Self::TarLz4(entry) => entry.path().map_err(From::from),
136
137 #[cfg(all(feature = "xz2", feature = "tar"))]
138 Self::TarXz(entry) => entry.path().map_err(From::from),
139
140 #[cfg(all(feature = "zstd", feature = "tar"))]
141 Self::TarZstd(entry) => entry.path().map_err(From::from),
142 }
143 }
144}
145
146impl Read for Entry<'_> {
147 fn read(
148 &mut self,
149 buf: &mut [u8],
150 ) -> std::result::Result<usize, std::io::Error> {
151 match self {
152 #[cfg(feature = "tar")]
153 Self::Tar(entry) => entry.read(buf),
154
155 #[cfg(all(feature = "bzip2", feature = "tar"))]
156 Self::TarBzip2(entry) => entry.read(buf),
157
158 #[cfg(all(feature = "bzip2-rs", feature = "tar"))]
159 Self::TarBzip2Rs(entry) => entry.read(buf),
160
161 #[cfg(all(feature = "flate2", feature = "tar"))]
162 Self::TarGzip(entry) => entry.read(buf),
163
164 #[cfg(all(feature = "lz4", feature = "tar"))]
165 Self::TarLz4(entry) => entry.read(buf),
166
167 #[cfg(all(feature = "xz2", feature = "tar"))]
168 Self::TarXz(entry) => entry.read(buf),
169
170 #[cfg(all(feature = "zstd", feature = "tar"))]
171 Self::TarZstd(entry) => entry.read(buf),
172 }
173 }
174}
175
176#[allow(clippy::module_name_repetitions)]
179#[derive(Clone, Copy, PartialEq, Eq, Debug)]
180#[non_exhaustive]
182#[must_use = "getting an entry type is used to inspect it"]
183pub enum EntryType {
184 Regular,
186
187 Link,
189
190 Symlink,
192
193 Char,
195
196 Block,
198
199 Directory,
201
202 Fifo,
204
205 Continuous,
207
208 GNULongName,
210
211 GNULongLink,
213
214 GNUSparse,
216
217 XGlobalHeader,
219
220 XHeader,
222
223 Other,
225}
226
227impl EntryType {
228 #[must_use = "side effect free function"]
230 pub fn is_file(&self) -> bool {
231 self == &Self::Regular
232 }
233}
234
235#[cfg(feature = "tar")]
236impl From<tar::EntryType> for EntryType {
237 fn from(e: tar::EntryType) -> Self {
238 match e {
239 tar::EntryType::Regular => Self::Regular,
240 tar::EntryType::Link => Self::Link,
241 tar::EntryType::Symlink => Self::Symlink,
242 tar::EntryType::Char => Self::Char,
243 tar::EntryType::Block => Self::Block,
244 tar::EntryType::Directory => Self::Directory,
245 tar::EntryType::Fifo => Self::Fifo,
246 tar::EntryType::Continuous => Self::Continuous,
247 tar::EntryType::GNULongName => Self::GNULongName,
248 tar::EntryType::GNULongLink => Self::GNULongLink,
249 tar::EntryType::GNUSparse => Self::GNUSparse,
250 tar::EntryType::XGlobalHeader => Self::XGlobalHeader,
251 tar::EntryType::XHeader => Self::XHeader,
252 _ => Self::Other,
253 }
254 }
255}