1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! Bounded decoding from an existing allocation: O(expanded bytes), no encoded copy.
use super::InputBuffer;
use super::collect::OutputLimit;
#[cfg(not(feature = "mmap"))]
use super::decode::decompress;
#[cfg(all(feature = "mmap", feature = "gzip"))]
use super::decode::map_gzip_reader;
#[cfg(all(feature = "mmap", feature = "zstd"))]
use super::decode::map_zstd_reader;
use super::{Compression, Limits};
use crate::diagnostic::Diagnostic;
impl InputBuffer {
/// Adopts plain bytes or decodes a gzip/Zstandard container within `limits`.
///
/// Plain bytes retain their allocation. Compressed bytes are decoded directly
/// from the supplied vector; expanded output uses private mapped storage when
/// `mmap` is enabled. [`Self::from_bytes`] deliberately performs no decoding.
///
/// ```
/// use molframe_core::io::{InputBuffer, Limits};
/// let bytes = b"data_example\n".to_vec();
/// let pointer = bytes.as_ptr();
/// let input = InputBuffer::from_encoded_bytes(bytes, Limits::default())?;
/// assert_eq!(input.as_bytes().as_ptr(), pointer);
/// # Ok::<(), molframe_core::diagnostic::Diagnostic>(())
/// ```
///
/// # Errors
///
/// Invalid containers, unavailable decoders, or exceeded byte/expansion limits.
pub fn from_encoded_bytes(bytes: Vec<u8>, limits: Limits) -> Result<Self, Diagnostic> {
let length = u64::try_from(bytes.len())
.map_err(|_| Limits::exceeded("decompressed bytes", bytes.len()))?;
OutputLimit::uncompressed(limits).validate(length)?;
let compression = Compression::sniff(&bytes);
if compression == Compression::None {
return Ok(Self::from_bytes(bytes));
}
#[cfg(not(feature = "mmap"))]
{
Ok(Self::from_bytes(decompress(bytes, limits)?))
}
#[cfg(feature = "mmap")]
{
match compression {
#[cfg(feature = "gzip")]
Compression::Gzip => {
map_gzip_reader(bytes.as_slice(), length, limits, None).map(Self::from_mapped)
}
#[cfg(not(feature = "gzip"))]
Compression::Gzip => Err(super::decode::unsupported("gzip")),
#[cfg(feature = "zstd")]
Compression::Zstd => {
map_zstd_reader(bytes.as_slice(), length, limits, None).map(Self::from_mapped)
}
#[cfg(not(feature = "zstd"))]
Compression::Zstd => Err(super::decode::unsupported("zstd")),
Compression::None => Ok(Self::from_bytes(bytes)),
}
}
}
}
#[cfg(test)]
#[path = "encoded_tests.rs"]
mod tests;