arch_pkg_db/text/
archive.rs

1mod gz;
2mod mime;
3mod tar;
4mod uncompressed;
5mod xz;
6
7pub use gz::LoadGzError;
8pub use lzma_rs::error::Error as LzmaError;
9pub use tar::LoadTarError;
10pub use uncompressed::LoadUncompressedArchiveError;
11pub use xz::LoadXzError;
12
13use super::{MultiTextCollection, TextCollection};
14use crate::value::RepositoryName;
15use derive_more::{Display, Error};
16use mime::SupportedCompressedArchiveType;
17use std::io;
18
19/// Error when trying to load data from an archive.
20#[derive(Debug, Display, Error)]
21pub enum LoadArchiveError {
22    #[display("Cannot detect mime type")]
23    GetMime,
24    #[display("Mime type not supported: {_0}")]
25    UnsupportedMimeType(#[error(not(source))] &'static str),
26    Tar(LoadTarError),
27    #[display("Failed to load the gzip archive: {_0}")]
28    Gzip(io::Error),
29    #[display("Failed to load the xz archive: {_0}")]
30    Xz(LzmaError),
31    #[display("Failed to extract data from the internal archive: {_0}")]
32    InternalArchive(LoadUncompressedArchiveError),
33}
34
35impl TextCollection {
36    /// Detect mime type of an archive, extract it, and add contents from `desc` files to the text collection.
37    pub fn extend_from_archive(&mut self, bytes: &[u8]) -> Result<(), LoadArchiveError> {
38        match SupportedCompressedArchiveType::check(bytes) {
39            Ok(SupportedCompressedArchiveType::Tar) => self.extend_from_tar(bytes)?,
40            Ok(SupportedCompressedArchiveType::Gzip) => self.extend_from_gz(bytes)?,
41            Ok(SupportedCompressedArchiveType::Xz) => self.extend_from_xz(bytes)?,
42            Err(Some(mime)) => return Err(LoadArchiveError::UnsupportedMimeType(mime)),
43            Err(None) => return Err(LoadArchiveError::GetMime),
44        }
45        Ok(())
46    }
47
48    /// Detect mime type of an archive, extract it, and add contents from `desc` files to the text collection.
49    pub fn add_archive(mut self, bytes: &[u8]) -> Result<Self, LoadArchiveError> {
50        self.extend_from_archive(bytes)?;
51        Ok(self)
52    }
53
54    /// Detect mime type of an archive, extract it, and add contents from `desc` files to the text collection.
55    pub fn from_archive(bytes: &[u8]) -> Result<Self, LoadArchiveError> {
56        TextCollection::new().add_archive(bytes)
57    }
58}
59
60impl<'a> MultiTextCollection<'a> {
61    /// Detect mime type of an archive, extract it, and add contents from `desc` files to the multi-collection.
62    pub fn extend_from_archive(
63        &mut self,
64        repository: RepositoryName<'a>,
65        bytes: &[u8],
66    ) -> Result<(), LoadArchiveError> {
67        let collection = TextCollection::from_archive(bytes)?;
68        self.insert(repository, collection);
69        Ok(())
70    }
71
72    /// Detect mime type of an archive, extract it, and add contents from `desc` files to the multi-collection.
73    pub fn add_archive(
74        mut self,
75        repository: RepositoryName<'a>,
76        bytes: &[u8],
77    ) -> Result<Self, LoadArchiveError> {
78        self.extend_from_archive(repository, bytes)?;
79        Ok(self)
80    }
81
82    /// Detect mime type of an archive, extract it, and add contents from `desc` files to the multi-collection.
83    pub fn from_archive(
84        repository: RepositoryName<'a>,
85        bytes: &[u8],
86    ) -> Result<Self, LoadArchiveError> {
87        MultiTextCollection::with_capacity(1).add_archive(repository, bytes)
88    }
89}