aboutsummaryrefslogtreecommitdiff
path: root/vendor/object/src/read/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/object/src/read/mod.rs')
-rw-r--r--vendor/object/src/read/mod.rs860
1 files changed, 0 insertions, 860 deletions
diff --git a/vendor/object/src/read/mod.rs b/vendor/object/src/read/mod.rs
deleted file mode 100644
index c13e309..0000000
--- a/vendor/object/src/read/mod.rs
+++ /dev/null
@@ -1,860 +0,0 @@
-//! Interface for reading object files.
-//!
-//! ## Unified read API
-//!
-//! The [`Object`] trait provides a unified read API for accessing common features of
-//! object files, such as sections and symbols. There is an implementation of this
-//! trait for [`File`], which allows reading any file format, as well as implementations
-//! for each file format:
-//! [`ElfFile`](elf::ElfFile), [`MachOFile`](macho::MachOFile), [`CoffFile`](coff::CoffFile),
-//! [`PeFile`](pe::PeFile), [`WasmFile`](wasm::WasmFile), [`XcoffFile`](xcoff::XcoffFile).
-//!
-//! ## Low level read API
-//!
-//! The submodules for each file format define helpers that operate on the raw structs.
-//! These can be used instead of the unified API, or in conjunction with it to access
-//! details that are not available via the unified API.
-//!
-//! See the [submodules](#modules) for examples of the low level read API.
-//!
-//! ## Naming Convention
-//!
-//! Types that form part of the unified API for a file format are prefixed with the
-//! name of the file format.
-//!
-//! ## Example for unified read API
-//! ```no_run
-//! use object::{Object, ObjectSection};
-//! use std::error::Error;
-//! use std::fs;
-//!
-//! /// Reads a file and displays the name of each section.
-//! fn main() -> Result<(), Box<dyn Error>> {
-//! # #[cfg(feature = "std")] {
-//! let data = fs::read("path/to/binary")?;
-//! let file = object::File::parse(&*data)?;
-//! for section in file.sections() {
-//! println!("{}", section.name()?);
-//! }
-//! # }
-//! Ok(())
-//! }
-//! ```
-
-use alloc::borrow::Cow;
-use alloc::vec::Vec;
-use core::{fmt, result};
-
-use crate::common::*;
-
-mod read_ref;
-pub use read_ref::*;
-
-#[cfg(feature = "std")]
-mod read_cache;
-#[cfg(feature = "std")]
-pub use read_cache::*;
-
-mod util;
-pub use util::*;
-
-#[cfg(any(
- feature = "coff",
- feature = "elf",
- feature = "macho",
- feature = "pe",
- feature = "wasm",
- feature = "xcoff"
-))]
-mod any;
-#[cfg(any(
- feature = "coff",
- feature = "elf",
- feature = "macho",
- feature = "pe",
- feature = "wasm",
- feature = "xcoff"
-))]
-pub use any::*;
-
-#[cfg(feature = "archive")]
-pub mod archive;
-
-#[cfg(feature = "coff")]
-pub mod coff;
-
-#[cfg(feature = "elf")]
-pub mod elf;
-
-#[cfg(feature = "macho")]
-pub mod macho;
-
-#[cfg(feature = "pe")]
-pub mod pe;
-
-#[cfg(feature = "wasm")]
-pub mod wasm;
-
-#[cfg(feature = "xcoff")]
-pub mod xcoff;
-
-mod traits;
-pub use traits::*;
-
-mod private {
- pub trait Sealed {}
-}
-
-/// The error type used within the read module.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct Error(&'static str);
-
-impl fmt::Display for Error {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(self.0)
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for Error {}
-
-/// The result type used within the read module.
-pub type Result<T> = result::Result<T, Error>;
-
-trait ReadError<T> {
- fn read_error(self, error: &'static str) -> Result<T>;
-}
-
-impl<T> ReadError<T> for result::Result<T, ()> {
- fn read_error(self, error: &'static str) -> Result<T> {
- self.map_err(|()| Error(error))
- }
-}
-
-impl<T> ReadError<T> for result::Result<T, Error> {
- fn read_error(self, error: &'static str) -> Result<T> {
- self.map_err(|_| Error(error))
- }
-}
-
-impl<T> ReadError<T> for Option<T> {
- fn read_error(self, error: &'static str) -> Result<T> {
- self.ok_or(Error(error))
- }
-}
-
-/// The native executable file for the target platform.
-#[cfg(all(
- unix,
- not(target_os = "macos"),
- target_pointer_width = "32",
- feature = "elf"
-))]
-pub type NativeFile<'data, R = &'data [u8]> = elf::ElfFile32<'data, crate::Endianness, R>;
-
-/// The native executable file for the target platform.
-#[cfg(all(
- unix,
- not(target_os = "macos"),
- target_pointer_width = "64",
- feature = "elf"
-))]
-pub type NativeFile<'data, R = &'data [u8]> = elf::ElfFile64<'data, crate::Endianness, R>;
-
-/// The native executable file for the target platform.
-#[cfg(all(target_os = "macos", target_pointer_width = "32", feature = "macho"))]
-pub type NativeFile<'data, R = &'data [u8]> = macho::MachOFile32<'data, crate::Endianness, R>;
-
-/// The native executable file for the target platform.
-#[cfg(all(target_os = "macos", target_pointer_width = "64", feature = "macho"))]
-pub type NativeFile<'data, R = &'data [u8]> = macho::MachOFile64<'data, crate::Endianness, R>;
-
-/// The native executable file for the target platform.
-#[cfg(all(target_os = "windows", target_pointer_width = "32", feature = "pe"))]
-pub type NativeFile<'data, R = &'data [u8]> = pe::PeFile32<'data, R>;
-
-/// The native executable file for the target platform.
-#[cfg(all(target_os = "windows", target_pointer_width = "64", feature = "pe"))]
-pub type NativeFile<'data, R = &'data [u8]> = pe::PeFile64<'data, R>;
-
-/// The native executable file for the target platform.
-#[cfg(all(feature = "wasm", target_arch = "wasm32", feature = "wasm"))]
-pub type NativeFile<'data, R = &'data [u8]> = wasm::WasmFile<'data, R>;
-
-/// A file format kind.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum FileKind {
- /// A Unix archive.
- ///
- /// See [`archive::ArchiveFile`].
- #[cfg(feature = "archive")]
- Archive,
- /// A COFF object file.
- ///
- /// See [`coff::CoffFile`].
- #[cfg(feature = "coff")]
- Coff,
- /// A COFF bigobj object file.
- ///
- /// This supports a larger number of sections.
- ///
- /// See [`coff::CoffBigFile`].
- #[cfg(feature = "coff")]
- CoffBig,
- /// A Windows short import file.
- ///
- /// See [`coff::ImportFile`].
- #[cfg(feature = "coff")]
- CoffImport,
- /// A dyld cache file containing Mach-O images.
- ///
- /// See [`macho::DyldCache`]
- #[cfg(feature = "macho")]
- DyldCache,
- /// A 32-bit ELF file.
- ///
- /// See [`elf::ElfFile32`].
- #[cfg(feature = "elf")]
- Elf32,
- /// A 64-bit ELF file.
- ///
- /// See [`elf::ElfFile64`].
- #[cfg(feature = "elf")]
- Elf64,
- /// A 32-bit Mach-O file.
- ///
- /// See [`macho::MachOFile32`].
- #[cfg(feature = "macho")]
- MachO32,
- /// A 64-bit Mach-O file.
- ///
- /// See [`macho::MachOFile64`].
- #[cfg(feature = "macho")]
- MachO64,
- /// A 32-bit Mach-O fat binary.
- ///
- /// See [`macho::FatHeader::parse_arch32`].
- #[cfg(feature = "macho")]
- MachOFat32,
- /// A 64-bit Mach-O fat binary.
- ///
- /// See [`macho::FatHeader::parse_arch64`].
- #[cfg(feature = "macho")]
- MachOFat64,
- /// A 32-bit PE file.
- ///
- /// See [`pe::PeFile32`].
- #[cfg(feature = "pe")]
- Pe32,
- /// A 64-bit PE file.
- ///
- /// See [`pe::PeFile64`].
- #[cfg(feature = "pe")]
- Pe64,
- /// A Wasm file.
- ///
- /// See [`wasm::WasmFile`].
- #[cfg(feature = "wasm")]
- Wasm,
- /// A 32-bit XCOFF file.
- ///
- /// See [`xcoff::XcoffFile32`].
- #[cfg(feature = "xcoff")]
- Xcoff32,
- /// A 64-bit XCOFF file.
- ///
- /// See [`xcoff::XcoffFile64`].
- #[cfg(feature = "xcoff")]
- Xcoff64,
-}
-
-impl FileKind {
- /// Determine a file kind by parsing the start of the file.
- pub fn parse<'data, R: ReadRef<'data>>(data: R) -> Result<FileKind> {
- Self::parse_at(data, 0)
- }
-
- /// Determine a file kind by parsing at the given offset.
- pub fn parse_at<'data, R: ReadRef<'data>>(data: R, offset: u64) -> Result<FileKind> {
- let magic = data
- .read_bytes_at(offset, 16)
- .read_error("Could not read file magic")?;
- if magic.len() < 16 {
- return Err(Error("File too short"));
- }
-
- let kind = match [magic[0], magic[1], magic[2], magic[3], magic[4], magic[5], magic[6], magic[7]] {
- #[cfg(feature = "archive")]
- [b'!', b'<', b'a', b'r', b'c', b'h', b'>', b'\n'] => FileKind::Archive,
- #[cfg(feature = "macho")]
- [b'd', b'y', b'l', b'd', b'_', b'v', b'1', b' '] => FileKind::DyldCache,
- #[cfg(feature = "elf")]
- [0x7f, b'E', b'L', b'F', 1, ..] => FileKind::Elf32,
- #[cfg(feature = "elf")]
- [0x7f, b'E', b'L', b'F', 2, ..] => FileKind::Elf64,
- #[cfg(feature = "macho")]
- [0xfe, 0xed, 0xfa, 0xce, ..]
- | [0xce, 0xfa, 0xed, 0xfe, ..] => FileKind::MachO32,
- #[cfg(feature = "macho")]
- | [0xfe, 0xed, 0xfa, 0xcf, ..]
- | [0xcf, 0xfa, 0xed, 0xfe, ..] => FileKind::MachO64,
- #[cfg(feature = "macho")]
- [0xca, 0xfe, 0xba, 0xbe, ..] => FileKind::MachOFat32,
- #[cfg(feature = "macho")]
- [0xca, 0xfe, 0xba, 0xbf, ..] => FileKind::MachOFat64,
- #[cfg(feature = "wasm")]
- [0x00, b'a', b's', b'm', ..] => FileKind::Wasm,
- #[cfg(feature = "pe")]
- [b'M', b'Z', ..] if offset == 0 => {
- // offset == 0 restriction is because optional_header_magic only looks at offset 0
- match pe::optional_header_magic(data) {
- Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC) => {
- FileKind::Pe32
- }
- Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC) => {
- FileKind::Pe64
- }
- _ => return Err(Error("Unknown MS-DOS file")),
- }
- }
- // TODO: more COFF machines
- #[cfg(feature = "coff")]
- // COFF arm
- [0xc4, 0x01, ..]
- // COFF arm64
- | [0x64, 0xaa, ..]
- // COFF arm64ec
- | [0x41, 0xa6, ..]
- // COFF x86
- | [0x4c, 0x01, ..]
- // COFF x86-64
- | [0x64, 0x86, ..] => FileKind::Coff,
- #[cfg(feature = "coff")]
- [0x00, 0x00, 0xff, 0xff, 0x00, 0x00, ..] => FileKind::CoffImport,
- #[cfg(feature = "coff")]
- [0x00, 0x00, 0xff, 0xff, 0x02, 0x00, ..] if offset == 0 => {
- // offset == 0 restriction is because anon_object_class_id only looks at offset 0
- match coff::anon_object_class_id(data) {
- Ok(crate::pe::ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID) => FileKind::CoffBig,
- _ => return Err(Error("Unknown anon object file")),
- }
- }
- #[cfg(feature = "xcoff")]
- [0x01, 0xdf, ..] => FileKind::Xcoff32,
- #[cfg(feature = "xcoff")]
- [0x01, 0xf7, ..] => FileKind::Xcoff64,
- _ => return Err(Error("Unknown file magic")),
- };
- Ok(kind)
- }
-}
-
-/// An object kind.
-///
-/// Returned by [`Object::kind`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum ObjectKind {
- /// The object kind is unknown.
- Unknown,
- /// Relocatable object.
- Relocatable,
- /// Executable.
- Executable,
- /// Dynamic shared object.
- Dynamic,
- /// Core.
- Core,
-}
-
-/// The index used to identify a section in a file.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct SectionIndex(pub usize);
-
-/// The index used to identify a symbol in a symbol table.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct SymbolIndex(pub usize);
-
-/// The section where an [`ObjectSymbol`] is defined.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum SymbolSection {
- /// The section is unknown.
- Unknown,
- /// The section is not applicable for this symbol (such as file symbols).
- None,
- /// The symbol is undefined.
- Undefined,
- /// The symbol has an absolute value.
- Absolute,
- /// The symbol is a zero-initialized symbol that will be combined with duplicate definitions.
- Common,
- /// The symbol is defined in the given section.
- Section(SectionIndex),
-}
-
-impl SymbolSection {
- /// Returns the section index for the section where the symbol is defined.
- ///
- /// May return `None` if the symbol is not defined in a section.
- #[inline]
- pub fn index(self) -> Option<SectionIndex> {
- if let SymbolSection::Section(index) = self {
- Some(index)
- } else {
- None
- }
- }
-}
-
-/// An entry in a [`SymbolMap`].
-pub trait SymbolMapEntry {
- /// The symbol address.
- fn address(&self) -> u64;
-}
-
-/// A map from addresses to symbol information.
-///
-/// The symbol information depends on the chosen entry type, such as [`SymbolMapName`].
-///
-/// Returned by [`Object::symbol_map`].
-#[derive(Debug, Default, Clone)]
-pub struct SymbolMap<T: SymbolMapEntry> {
- symbols: Vec<T>,
-}
-
-impl<T: SymbolMapEntry> SymbolMap<T> {
- /// Construct a new symbol map.
- ///
- /// This function will sort the symbols by address.
- pub fn new(mut symbols: Vec<T>) -> Self {
- symbols.sort_by_key(|s| s.address());
- SymbolMap { symbols }
- }
-
- /// Get the symbol before the given address.
- pub fn get(&self, address: u64) -> Option<&T> {
- let index = match self
- .symbols
- .binary_search_by_key(&address, |symbol| symbol.address())
- {
- Ok(index) => index,
- Err(index) => index.checked_sub(1)?,
- };
- self.symbols.get(index)
- }
-
- /// Get all symbols in the map.
- #[inline]
- pub fn symbols(&self) -> &[T] {
- &self.symbols
- }
-}
-
-/// The type used for entries in a [`SymbolMap`] that maps from addresses to names.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct SymbolMapName<'data> {
- address: u64,
- name: &'data str,
-}
-
-impl<'data> SymbolMapName<'data> {
- /// Construct a `SymbolMapName`.
- pub fn new(address: u64, name: &'data str) -> Self {
- SymbolMapName { address, name }
- }
-
- /// The symbol address.
- #[inline]
- pub fn address(&self) -> u64 {
- self.address
- }
-
- /// The symbol name.
- #[inline]
- pub fn name(&self) -> &'data str {
- self.name
- }
-}
-
-impl<'data> SymbolMapEntry for SymbolMapName<'data> {
- #[inline]
- fn address(&self) -> u64 {
- self.address
- }
-}
-
-/// A map from addresses to symbol names and object files.
-///
-/// This is derived from STAB entries in Mach-O files.
-///
-/// Returned by [`Object::object_map`].
-#[derive(Debug, Default, Clone)]
-pub struct ObjectMap<'data> {
- symbols: SymbolMap<ObjectMapEntry<'data>>,
- objects: Vec<&'data [u8]>,
-}
-
-impl<'data> ObjectMap<'data> {
- /// Get the entry containing the given address.
- pub fn get(&self, address: u64) -> Option<&ObjectMapEntry<'data>> {
- self.symbols
- .get(address)
- .filter(|entry| entry.size == 0 || address.wrapping_sub(entry.address) < entry.size)
- }
-
- /// Get all symbols in the map.
- #[inline]
- pub fn symbols(&self) -> &[ObjectMapEntry<'data>] {
- self.symbols.symbols()
- }
-
- /// Get all objects in the map.
- #[inline]
- pub fn objects(&self) -> &[&'data [u8]] {
- &self.objects
- }
-}
-
-/// An [`ObjectMap`] entry.
-#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct ObjectMapEntry<'data> {
- address: u64,
- size: u64,
- name: &'data [u8],
- object: usize,
-}
-
-impl<'data> ObjectMapEntry<'data> {
- /// Get the symbol address.
- #[inline]
- pub fn address(&self) -> u64 {
- self.address
- }
-
- /// Get the symbol size.
- ///
- /// This may be 0 if the size is unknown.
- #[inline]
- pub fn size(&self) -> u64 {
- self.size
- }
-
- /// Get the symbol name.
- #[inline]
- pub fn name(&self) -> &'data [u8] {
- self.name
- }
-
- /// Get the index of the object file name.
- #[inline]
- pub fn object_index(&self) -> usize {
- self.object
- }
-
- /// Get the object file name.
- #[inline]
- pub fn object(&self, map: &ObjectMap<'data>) -> &'data [u8] {
- map.objects[self.object]
- }
-}
-
-impl<'data> SymbolMapEntry for ObjectMapEntry<'data> {
- #[inline]
- fn address(&self) -> u64 {
- self.address
- }
-}
-
-/// An imported symbol.
-///
-/// Returned by [`Object::imports`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct Import<'data> {
- library: ByteString<'data>,
- // TODO: or ordinal
- name: ByteString<'data>,
-}
-
-impl<'data> Import<'data> {
- /// The symbol name.
- #[inline]
- pub fn name(&self) -> &'data [u8] {
- self.name.0
- }
-
- /// The name of the library to import the symbol from.
- #[inline]
- pub fn library(&self) -> &'data [u8] {
- self.library.0
- }
-}
-
-/// An exported symbol.
-///
-/// Returned by [`Object::exports`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct Export<'data> {
- // TODO: and ordinal?
- name: ByteString<'data>,
- address: u64,
-}
-
-impl<'data> Export<'data> {
- /// The symbol name.
- #[inline]
- pub fn name(&self) -> &'data [u8] {
- self.name.0
- }
-
- /// The virtual address of the symbol.
- #[inline]
- pub fn address(&self) -> u64 {
- self.address
- }
-}
-
-/// PDB information from the debug directory in a PE file.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct CodeView<'data> {
- guid: [u8; 16],
- path: ByteString<'data>,
- age: u32,
-}
-
-impl<'data> CodeView<'data> {
- /// The path to the PDB as stored in CodeView.
- #[inline]
- pub fn path(&self) -> &'data [u8] {
- self.path.0
- }
-
- /// The age of the PDB.
- #[inline]
- pub fn age(&self) -> u32 {
- self.age
- }
-
- /// The GUID of the PDB.
- #[inline]
- pub fn guid(&self) -> [u8; 16] {
- self.guid
- }
-}
-
-/// The target referenced by a [`Relocation`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum RelocationTarget {
- /// The target is a symbol.
- Symbol(SymbolIndex),
- /// The target is a section.
- Section(SectionIndex),
- /// The offset is an absolute address.
- Absolute,
-}
-
-/// A relocation entry.
-///
-/// Returned by [`Object::dynamic_relocations`] or [`ObjectSection::relocations`].
-#[derive(Debug)]
-pub struct Relocation {
- kind: RelocationKind,
- encoding: RelocationEncoding,
- size: u8,
- target: RelocationTarget,
- addend: i64,
- implicit_addend: bool,
-}
-
-impl Relocation {
- /// The operation used to calculate the result of the relocation.
- #[inline]
- pub fn kind(&self) -> RelocationKind {
- self.kind
- }
-
- /// Information about how the result of the relocation operation is encoded in the place.
- #[inline]
- pub fn encoding(&self) -> RelocationEncoding {
- self.encoding
- }
-
- /// The size in bits of the place of the relocation.
- ///
- /// If 0, then the size is determined by the relocation kind.
- #[inline]
- pub fn size(&self) -> u8 {
- self.size
- }
-
- /// The target of the relocation.
- #[inline]
- pub fn target(&self) -> RelocationTarget {
- self.target
- }
-
- /// The addend to use in the relocation calculation.
- #[inline]
- pub fn addend(&self) -> i64 {
- self.addend
- }
-
- /// Set the addend to use in the relocation calculation.
- #[inline]
- pub fn set_addend(&mut self, addend: i64) {
- self.addend = addend
- }
-
- /// Returns true if there is an implicit addend stored in the data at the offset
- /// to be relocated.
- #[inline]
- pub fn has_implicit_addend(&self) -> bool {
- self.implicit_addend
- }
-}
-
-/// A data compression format.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum CompressionFormat {
- /// The data is uncompressed.
- None,
- /// The data is compressed, but the compression format is unknown.
- Unknown,
- /// ZLIB/DEFLATE.
- ///
- /// Used for ELF compression and GNU compressed debug information.
- Zlib,
- /// Zstandard.
- ///
- /// Used for ELF compression.
- Zstandard,
-}
-
-/// A range in a file that may be compressed.
-///
-/// Returned by [`ObjectSection::compressed_file_range`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct CompressedFileRange {
- /// The data compression format.
- pub format: CompressionFormat,
- /// The file offset of the compressed data.
- pub offset: u64,
- /// The compressed data size.
- pub compressed_size: u64,
- /// The uncompressed data size.
- pub uncompressed_size: u64,
-}
-
-impl CompressedFileRange {
- /// Data that is uncompressed.
- #[inline]
- pub fn none(range: Option<(u64, u64)>) -> Self {
- if let Some((offset, size)) = range {
- CompressedFileRange {
- format: CompressionFormat::None,
- offset,
- compressed_size: size,
- uncompressed_size: size,
- }
- } else {
- CompressedFileRange {
- format: CompressionFormat::None,
- offset: 0,
- compressed_size: 0,
- uncompressed_size: 0,
- }
- }
- }
-
- /// Convert to [`CompressedData`] by reading from the file.
- pub fn data<'data, R: ReadRef<'data>>(self, file: R) -> Result<CompressedData<'data>> {
- let data = file
- .read_bytes_at(self.offset, self.compressed_size)
- .read_error("Invalid compressed data size or offset")?;
- Ok(CompressedData {
- format: self.format,
- data,
- uncompressed_size: self.uncompressed_size,
- })
- }
-}
-
-/// Data that may be compressed.
-///
-/// Returned by [`ObjectSection::compressed_data`].
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct CompressedData<'data> {
- /// The data compression format.
- pub format: CompressionFormat,
- /// The compressed data.
- pub data: &'data [u8],
- /// The uncompressed data size.
- pub uncompressed_size: u64,
-}
-
-impl<'data> CompressedData<'data> {
- /// Data that is uncompressed.
- #[inline]
- pub fn none(data: &'data [u8]) -> Self {
- CompressedData {
- format: CompressionFormat::None,
- data,
- uncompressed_size: data.len() as u64,
- }
- }
-
- /// Return the uncompressed data.
- ///
- /// Returns an error for invalid data or unsupported compression.
- /// This includes if the data is compressed but the `compression` feature
- /// for this crate is disabled.
- pub fn decompress(self) -> Result<Cow<'data, [u8]>> {
- match self.format {
- CompressionFormat::None => Ok(Cow::Borrowed(self.data)),
- #[cfg(feature = "compression")]
- CompressionFormat::Zlib => {
- use core::convert::TryInto;
- let size = self
- .uncompressed_size
- .try_into()
- .ok()
- .read_error("Uncompressed data size is too large.")?;
- let mut decompressed = Vec::with_capacity(size);
- let mut decompress = flate2::Decompress::new(true);
- decompress
- .decompress_vec(
- self.data,
- &mut decompressed,
- flate2::FlushDecompress::Finish,
- )
- .ok()
- .read_error("Invalid zlib compressed data")?;
- Ok(Cow::Owned(decompressed))
- }
- #[cfg(feature = "compression")]
- CompressionFormat::Zstandard => {
- use core::convert::TryInto;
- use std::io::Read;
- let size = self
- .uncompressed_size
- .try_into()
- .ok()
- .read_error("Uncompressed data size is too large.")?;
- let mut decompressed = Vec::with_capacity(size);
- let mut decoder = ruzstd::StreamingDecoder::new(self.data)
- .ok()
- .read_error("Invalid zstd compressed data")?;
- decoder
- .read_to_end(&mut decompressed)
- .ok()
- .read_error("Invalid zstd compressed data")?;
- Ok(Cow::Owned(decompressed))
- }
- _ => Err(Error("Unsupported compressed data.")),
- }
- }
-}