@@ -15,10 +15,12 @@ use std::{
15
15
use tar:: Archive ;
16
16
use tokio:: task;
17
17
use tracing:: info;
18
+ use zstd:: stream:: read:: Decoder as ZstdDecoder ;
18
19
19
20
const BYTE_UNITS : [ & str ; 4 ] = [ "B" , "KB" , "MB" , "GB" ] ;
20
21
const MERKLE_BASE_URL : & str = "https://downloads.merkle.io" ;
21
- const EXTENSION_TAR_FILE : & str = ".tar.lz4" ;
22
+ const EXTENSION_TAR_LZ4 : & str = ".tar.lz4" ;
23
+ const EXTENSION_TAR_ZSTD : & str = ".tar.zst" ;
22
24
23
25
#[ derive( Debug , Parser ) ]
24
26
pub struct DownloadCommand < C : ChainSpecParser > {
@@ -148,7 +150,27 @@ impl<R: Read> Read for ProgressReader<R> {
148
150
}
149
151
}
150
152
151
- /// Downloads and extracts a snapshot with blocking approach
153
+ /// Supported compression formats for snapshots
154
+ #[ derive( Debug , Clone , Copy ) ]
155
+ enum CompressionFormat {
156
+ Lz4 ,
157
+ Zstd ,
158
+ }
159
+
160
+ impl CompressionFormat {
161
+ /// Detect compression format from file extension
162
+ fn from_url ( url : & str ) -> Result < Self > {
163
+ if url. ends_with ( EXTENSION_TAR_LZ4 ) {
164
+ Ok ( Self :: Lz4 )
165
+ } else if url. ends_with ( EXTENSION_TAR_ZSTD ) {
166
+ Ok ( Self :: Zstd )
167
+ } else {
168
+ Err ( eyre:: eyre!( "Unsupported file format. Expected .tar.lz4 or .tar.zst, got: {}" , url) )
169
+ }
170
+ }
171
+ }
172
+
173
+ /// Downloads and extracts a snapshot, blocking until finished.
152
174
fn blocking_download_and_extract ( url : & str , target_dir : & Path ) -> Result < ( ) > {
153
175
let client = reqwest:: blocking:: Client :: builder ( ) . build ( ) ?;
154
176
let response = client. get ( url) . send ( ) ?. error_for_status ( ) ?;
@@ -160,11 +182,18 @@ fn blocking_download_and_extract(url: &str, target_dir: &Path) -> Result<()> {
160
182
} ) ?;
161
183
162
184
let progress_reader = ProgressReader :: new ( response, total_size) ;
185
+ let format = CompressionFormat :: from_url ( url) ?;
163
186
164
- let decoder = Decoder :: new ( progress_reader) ?;
165
- let mut archive = Archive :: new ( decoder) ;
166
-
167
- archive. unpack ( target_dir) ?;
187
+ match format {
188
+ CompressionFormat :: Lz4 => {
189
+ let decoder = Decoder :: new ( progress_reader) ?;
190
+ Archive :: new ( decoder) . unpack ( target_dir) ?;
191
+ }
192
+ CompressionFormat :: Zstd => {
193
+ let decoder = ZstdDecoder :: new ( progress_reader) ?;
194
+ Archive :: new ( decoder) . unpack ( target_dir) ?;
195
+ }
196
+ }
168
197
169
198
info ! ( target: "reth::cli" , "Extraction complete." ) ;
170
199
Ok ( ( ) )
@@ -191,9 +220,5 @@ async fn get_latest_snapshot_url() -> Result<String> {
191
220
. trim ( )
192
221
. to_string ( ) ;
193
222
194
- if !filename. ends_with ( EXTENSION_TAR_FILE ) {
195
- return Err ( eyre:: eyre!( "Unexpected snapshot filename format: {}" , filename) ) ;
196
- }
197
-
198
223
Ok ( format ! ( "{MERKLE_BASE_URL}/{filename}" ) )
199
224
}
0 commit comments