Mercurial > hg
annotate rust/hg-core/src/revlog/compression.rs @ 52309:f69a3f55fa9b
rust-compression: move the `Send` bound to the `Compressor` trait
All compressors should be `Send`, might as well make any future use easier.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 04 Nov 2024 13:43:36 +0100 |
parents | 0744248cc541 |
children |
rev | line source |
---|---|
52158
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
1 //! Helpers around revlog compression |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
3 use std::cell::RefCell; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
4 use std::collections::HashSet; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
5 use std::io::Read; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
6 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
7 use flate2::bufread::ZlibEncoder; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
8 use flate2::read::ZlibDecoder; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
9 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
10 use crate::config::Config; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
11 use crate::errors::HgError; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
12 use crate::exit_codes; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
13 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
14 use super::corrupted; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
15 use super::RevlogError; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
16 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
17 /// Header byte used to identify ZSTD-compressed data |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
18 pub const ZSTD_BYTE: u8 = b'\x28'; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
19 /// Header byte used to identify Zlib-compressed data |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
20 pub const ZLIB_BYTE: u8 = b'x'; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
21 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
22 const ZSTD_DEFAULT_LEVEL: u8 = 3; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
23 const ZLIB_DEFAULT_LEVEL: u8 = 6; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
24 /// The length of data below which we don't even try to compress it when using |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
25 /// Zstandard. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
26 const MINIMUM_LENGTH_ZSTD: usize = 50; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
27 /// The length of data below which we don't even try to compress it when using |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
28 /// Zlib. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
29 const MINIMUM_LENGTH_ZLIB: usize = 44; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
30 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
31 /// Defines the available compression engines and their options. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
32 #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
33 pub enum CompressionConfig { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
34 Zlib { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
35 /// Between 0 and 9 included |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
36 level: u8, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
37 }, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
38 Zstd { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
39 /// Between 0 and 22 included |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
40 level: u8, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
41 /// Never used in practice for now |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
42 threads: u8, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
43 }, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
44 /// No compression is performed |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
45 None, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
46 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
47 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
48 impl CompressionConfig { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
49 pub fn new( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
50 config: &Config, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
51 requirements: &HashSet<String>, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
52 ) -> Result<Self, HgError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
53 let mut new = Self::default(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
54 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
55 let zlib_level = config.get_u32(b"storage", b"revlog.zlib.level")?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
56 let zstd_level = config.get_u32(b"storage", b"revlog.zstd.level")?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
57 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
58 for requirement in requirements { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
59 if requirement.starts_with("revlog-compression-") |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
60 || requirement.starts_with("exp-compression-") |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
61 { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
62 let split = &mut requirement.splitn(3, '-'); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
63 split.next(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
64 split.next(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
65 new = match split.next().unwrap() { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
66 "zstd" => CompressionConfig::zstd(zstd_level)?, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
67 e => { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
68 return Err(HgError::UnsupportedFeature(format!( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
69 "Unsupported compression engine '{e}'" |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
70 ))) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
71 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
72 }; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
73 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
74 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
75 if let Some(level) = zlib_level { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
76 if matches!(new, CompressionConfig::Zlib { .. }) { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
77 new.set_level(level as usize)?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
78 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
79 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
80 Ok(new) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
81 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
82 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
83 /// Sets the level of the current compression engine |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
84 pub fn set_level(&mut self, new_level: usize) -> Result<(), HgError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
85 match self { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
86 CompressionConfig::Zlib { level } => { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
87 if new_level > 9 { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
88 return Err(HgError::abort( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
89 format!( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
90 "invalid compression zlib compression level {}, \ |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
91 expected between 0 and 9 included", |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
92 new_level |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
93 ), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
94 exit_codes::ABORT, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
95 None, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
96 )); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
97 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
98 *level = new_level as u8; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
99 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
100 CompressionConfig::Zstd { level, .. } => { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
101 if new_level > 22 { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
102 return Err(HgError::abort( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
103 format!( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
104 "invalid compression zstd compression level {}, \ |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
105 expected between 0 and 22 included", |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
106 new_level |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
107 ), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
108 exit_codes::ABORT, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
109 None, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
110 )); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
111 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
112 *level = new_level as u8; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
113 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
114 CompressionConfig::None => {} |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
115 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
116 Ok(()) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
117 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
118 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
119 /// Return a ZSTD compression config |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
120 pub fn zstd( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
121 zstd_level: Option<u32>, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
122 ) -> Result<CompressionConfig, HgError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
123 let mut engine = CompressionConfig::Zstd { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
124 level: ZSTD_DEFAULT_LEVEL, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
125 threads: 0, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
126 }; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
127 if let Some(level) = zstd_level { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
128 engine.set_level(level as usize)?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
129 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
130 Ok(engine) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
131 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
132 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
133 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
134 impl Default for CompressionConfig { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
135 fn default() -> Self { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
136 Self::Zlib { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
137 level: ZLIB_DEFAULT_LEVEL, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
138 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
139 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
140 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
141 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
142 /// A high-level trait to define compressors that should be able to compress |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
143 /// and decompress arbitrary bytes. |
52309
f69a3f55fa9b
rust-compression: move the `Send` bound to the `Compressor` trait
Raphaël Gomès <rgomes@octobus.net>
parents:
52158
diff
changeset
|
144 pub trait Compressor: Send { |
52158
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
145 /// Returns a new [`Vec`] with the compressed data. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
146 /// Should return `Ok(None)` if compression does not apply (e.g. too small) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
147 fn compress( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
148 &mut self, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
149 data: &[u8], |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
150 ) -> Result<Option<Vec<u8>>, RevlogError>; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
151 /// Returns a new [`Vec`] with the decompressed data. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
152 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, RevlogError>; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
153 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
154 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
155 /// A compressor that does nothing (useful in tests) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
156 pub struct NoneCompressor; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
157 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
158 impl Compressor for NoneCompressor { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
159 fn compress( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
160 &mut self, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
161 _data: &[u8], |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
162 ) -> Result<Option<Vec<u8>>, RevlogError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
163 Ok(None) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
164 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
165 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
166 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, RevlogError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
167 Ok(data.to_owned()) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
168 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
169 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
170 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
171 /// A compressor for Zstandard |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
172 pub struct ZstdCompressor { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
173 /// Level of compression to use |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
174 level: u8, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
175 /// How many threads are used (not implemented yet) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
176 threads: u8, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
177 /// The underlying zstd compressor |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
178 compressor: zstd::bulk::Compressor<'static>, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
179 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
180 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
181 impl ZstdCompressor { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
182 pub fn new(level: u8, threads: u8) -> Self { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
183 Self { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
184 level, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
185 threads, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
186 compressor: zstd::bulk::Compressor::new(level.into()) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
187 .expect("invalid zstd arguments"), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
188 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
189 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
190 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
191 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
192 impl Compressor for ZstdCompressor { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
193 fn compress( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
194 &mut self, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
195 data: &[u8], |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
196 ) -> Result<Option<Vec<u8>>, RevlogError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
197 if self.threads != 0 { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
198 // TODO use a zstd builder + zstd cargo feature to support this |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
199 unimplemented!("zstd parallel compression is not implemented"); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
200 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
201 if data.len() < MINIMUM_LENGTH_ZSTD { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
202 return Ok(None); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
203 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
204 let level = self.level as i32; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
205 if data.len() <= 1000000 { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
206 let compressed = self.compressor.compress(data).map_err(|e| { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
207 corrupted(format!("revlog compress error: {}", e)) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
208 })?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
209 Ok(if compressed.len() < data.len() { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
210 Some(compressed) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
211 } else { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
212 None |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
213 }) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
214 } else { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
215 Ok(Some(zstd::stream::encode_all(data, level).map_err( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
216 |e| corrupted(format!("revlog compress error: {}", e)), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
217 )?)) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
218 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
219 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
220 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
221 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, RevlogError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
222 zstd::stream::decode_all(data).map_err(|e| { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
223 corrupted(format!("revlog decompress error: {}", e)).into() |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
224 }) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
225 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
226 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
227 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
228 /// A compressor for Zlib |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
229 pub struct ZlibCompressor { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
230 /// Level of compression to use |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
231 level: flate2::Compression, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
232 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
233 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
234 impl ZlibCompressor { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
235 pub fn new(level: u8) -> Self { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
236 Self { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
237 level: flate2::Compression::new(level.into()), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
238 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
239 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
240 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
241 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
242 impl Compressor for ZlibCompressor { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
243 fn compress( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
244 &mut self, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
245 data: &[u8], |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
246 ) -> Result<Option<Vec<u8>>, RevlogError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
247 assert!(!data.is_empty()); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
248 if data.len() < MINIMUM_LENGTH_ZLIB { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
249 return Ok(None); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
250 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
251 let mut buf = Vec::with_capacity(data.len()); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
252 ZlibEncoder::new(data, self.level) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
253 .read_to_end(&mut buf) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
254 .map_err(|e| corrupted(format!("revlog compress error: {}", e)))?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
255 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
256 Ok(if buf.len() < data.len() { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
257 buf.shrink_to_fit(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
258 Some(buf) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
259 } else { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
260 None |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
261 }) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
262 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
263 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
264 fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, RevlogError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
265 let mut decoder = ZlibDecoder::new(data); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
266 // TODO reuse the allocation somehow? |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
267 let mut buf = vec![]; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
268 decoder.read_to_end(&mut buf).map_err(|e| { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
269 corrupted(format!("revlog decompress error: {}", e)) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
270 })?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
271 Ok(buf) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
272 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
273 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
274 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
275 thread_local! { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
276 // seems fine to [unwrap] here: this can only fail due to memory allocation |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
277 // failing, and it's normal for that to cause panic. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
278 static ZSTD_DECODER : RefCell<zstd::bulk::Decompressor<'static>> = |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
279 RefCell::new(zstd::bulk::Decompressor::new().ok().unwrap()); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
280 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
281 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
282 /// Util to wrap the reuse of a zstd decoder while controlling its buffer size. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
283 fn zstd_decompress_to_buffer( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
284 bytes: &[u8], |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
285 buf: &mut Vec<u8>, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
286 ) -> Result<usize, std::io::Error> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
287 ZSTD_DECODER |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
288 .with(|decoder| decoder.borrow_mut().decompress_to_buffer(bytes, buf)) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
289 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
290 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
291 /// Specialized revlog decompression to use less memory for deltas while |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
292 /// keeping performance acceptable. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
293 pub(super) fn uncompressed_zstd_data( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
294 bytes: &[u8], |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
295 is_delta: bool, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
296 uncompressed_len: i32, |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
297 ) -> Result<Vec<u8>, HgError> { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
298 let cap = uncompressed_len.max(0) as usize; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
299 if is_delta { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
300 // [cap] is usually an over-estimate of the space needed because |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
301 // it's the length of delta-decoded data, but we're interested |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
302 // in the size of the delta. |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
303 // This means we have to [shrink_to_fit] to avoid holding on |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
304 // to a large chunk of memory, but it also means we must have a |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
305 // fallback branch, for the case when the delta is longer than |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
306 // the original data (surprisingly, this does happen in practice) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
307 let mut buf = Vec::with_capacity(cap); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
308 match zstd_decompress_to_buffer(bytes, &mut buf) { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
309 Ok(_) => buf.shrink_to_fit(), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
310 Err(_) => { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
311 buf.clear(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
312 zstd::stream::copy_decode(bytes, &mut buf) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
313 .map_err(|e| corrupted(e.to_string()))?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
314 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
315 }; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
316 Ok(buf) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
317 } else { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
318 let mut buf = Vec::with_capacity(cap); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
319 let len = zstd_decompress_to_buffer(bytes, &mut buf) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
320 .map_err(|e| corrupted(e.to_string()))?; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
321 if len != uncompressed_len as usize { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
322 Err(corrupted("uncompressed length does not match")) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
323 } else { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
324 Ok(buf) |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
325 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
326 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
327 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
328 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
329 #[cfg(test)] |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
330 mod tests { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
331 use super::*; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
332 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
333 const LARGE_TEXT: &[u8] = b" |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
334 Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
335 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
336 Emana Karassoli, Loucra Loucra Nonponto, Pata Pata, Ko Ko Ko."; |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
337 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
338 #[test] |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
339 fn test_zlib_compressor() { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
340 // Can return `Ok(None)` |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
341 let mut compressor = ZlibCompressor::new(1); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
342 assert_eq!(compressor.compress(b"too small").unwrap(), None); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
343 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
344 // Compression returns bytes |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
345 let compressed_with_1 = |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
346 compressor.compress(LARGE_TEXT).unwrap().unwrap(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
347 assert!(compressed_with_1.len() < LARGE_TEXT.len()); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
348 // Round trip works |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
349 assert_eq!( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
350 compressor.decompress(&compressed_with_1).unwrap(), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
351 LARGE_TEXT |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
352 ); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
353 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
354 // Compression levels mean something |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
355 let mut compressor = ZlibCompressor::new(9); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
356 // Compression returns bytes |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
357 let compressed = compressor.compress(LARGE_TEXT).unwrap().unwrap(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
358 assert!(compressed.len() < compressed_with_1.len()); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
359 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
360 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
361 #[test] |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
362 fn test_zstd_compressor() { |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
363 // Can return `Ok(None)` |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
364 let mut compressor = ZstdCompressor::new(1, 0); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
365 assert_eq!(compressor.compress(b"too small").unwrap(), None); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
366 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
367 // Compression returns bytes |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
368 let compressed_with_1 = |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
369 compressor.compress(LARGE_TEXT).unwrap().unwrap(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
370 assert!(compressed_with_1.len() < LARGE_TEXT.len()); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
371 // Round trip works |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
372 assert_eq!( |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
373 compressor.decompress(&compressed_with_1).unwrap(), |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
374 LARGE_TEXT |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
375 ); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
376 |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
377 // Compression levels mean something |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
378 let mut compressor = ZstdCompressor::new(22, 0); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
379 // Compression returns bytes |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
380 let compressed = compressor.compress(LARGE_TEXT).unwrap().unwrap(); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
381 assert!(compressed.len() < compressed_with_1.len()); |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
382 } |
0744248cc541
rust-revlog: add compression helpers
Raphaël Gomès <rgomes@octobus.net>
parents:
diff
changeset
|
383 } |