readcon_core/
compression.rs1use std::io::{self, Read};
6use std::path::Path;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Compression {
11 None,
12 Gzip,
13}
14
15pub fn detect_compression(bytes: &[u8]) -> Compression {
20 if bytes.len() >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b {
21 return Compression::Gzip;
22 }
23 Compression::None
24}
25
26pub fn detect_compression_from_extension(path: &Path) -> Compression {
30 match path.extension().and_then(|e| e.to_str()) {
31 Some("gz") => Compression::Gzip,
32 _ => Compression::None,
33 }
34}
35
36const MMAP_THRESHOLD: u64 = 64 * 1024;
38
39pub fn read_file_contents(path: &Path) -> Result<FileContents, Box<dyn std::error::Error>> {
47 let file = std::fs::File::open(path)?;
48 let metadata = file.metadata()?;
49
50 let mut magic = [0u8; 2];
52 let bytes_read = {
53 let mut f = &file;
54 f.read(&mut magic)?
55 };
56
57 let compression = if bytes_read >= 2 {
58 detect_compression(&magic)
59 } else {
60 Compression::None
61 };
62
63 match compression {
64 Compression::Gzip => {
65 let file = std::fs::File::open(path)?;
67 let mut decoder = flate2::read::GzDecoder::new(file);
68 let mut contents = String::new();
69 decoder.read_to_string(&mut contents)?;
70 Ok(FileContents::Owned(contents))
71 }
72 Compression::None => {
73 if metadata.len() < MMAP_THRESHOLD {
74 let contents = std::fs::read_to_string(path)?;
75 Ok(FileContents::Owned(contents))
76 } else {
77 let file = std::fs::File::open(path)?;
78 let mmap = unsafe { memmap2::Mmap::map(&file)? };
79 Ok(FileContents::Mapped(mmap))
80 }
81 }
82 }
83}
84
85pub enum FileContents {
87 Owned(String),
88 Mapped(memmap2::Mmap),
89}
90
91impl FileContents {
92 pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> {
93 match self {
94 FileContents::Owned(s) => Ok(s.as_str()),
95 FileContents::Mapped(m) => std::str::from_utf8(m),
96 }
97 }
98}
99
100pub fn gzip_writer(path: &Path) -> io::Result<flate2::write::GzEncoder<std::fs::File>> {
102 let file = std::fs::File::create(path)?;
103 Ok(flate2::write::GzEncoder::new(
104 file,
105 flate2::Compression::default(),
106 ))
107}