solana_runtime/snapshot_utils/
archive_format.rs1use {
2 std::{fmt, str::FromStr},
3 strum::Display,
4};
5
6pub const SUPPORTED_ARCHIVE_COMPRESSION: &[&str] = &["zstd", "lz4"];
13pub const DEFAULT_ARCHIVE_COMPRESSION: &str = "zstd";
14
15pub const TAR_BZIP2_EXTENSION: &str = "tar.bz2";
16pub const TAR_GZIP_EXTENSION: &str = "tar.gz";
17pub const TAR_ZSTD_EXTENSION: &str = "tar.zst";
18pub const TAR_LZ4_EXTENSION: &str = "tar.lz4";
19pub const TAR_EXTENSION: &str = "tar";
20
21#[derive(Copy, Clone, Debug, Eq, PartialEq, Display)]
23pub enum ArchiveFormat {
24 TarBzip2,
25 TarGzip,
26 TarZstd { config: ZstdConfig },
27 TarLz4,
28 Tar,
29}
30
31impl ArchiveFormat {
32 pub fn extension(&self) -> &str {
34 match self {
35 ArchiveFormat::TarBzip2 => TAR_BZIP2_EXTENSION,
36 ArchiveFormat::TarGzip => TAR_GZIP_EXTENSION,
37 ArchiveFormat::TarZstd { .. } => TAR_ZSTD_EXTENSION,
38 ArchiveFormat::TarLz4 => TAR_LZ4_EXTENSION,
39 ArchiveFormat::Tar => TAR_EXTENSION,
40 }
41 }
42
43 pub fn from_cli_arg(archive_format_str: &str) -> Option<ArchiveFormat> {
44 match archive_format_str {
45 "zstd" => Some(ArchiveFormat::TarZstd {
46 config: ZstdConfig::default(),
47 }),
48 "lz4" => Some(ArchiveFormat::TarLz4),
49 _ => None,
50 }
51 }
52}
53
54impl TryFrom<&str> for ArchiveFormat {
57 type Error = ParseError;
58
59 fn try_from(extension: &str) -> Result<Self, Self::Error> {
60 match extension {
61 TAR_BZIP2_EXTENSION => Ok(ArchiveFormat::TarBzip2),
62 TAR_GZIP_EXTENSION => Ok(ArchiveFormat::TarGzip),
63 TAR_ZSTD_EXTENSION => Ok(ArchiveFormat::TarZstd {
64 config: ZstdConfig::default(),
65 }),
66 TAR_LZ4_EXTENSION => Ok(ArchiveFormat::TarLz4),
67 TAR_EXTENSION => Ok(ArchiveFormat::Tar),
68 _ => Err(ParseError::InvalidExtension(extension.to_string())),
69 }
70 }
71}
72
73impl FromStr for ArchiveFormat {
74 type Err = ParseError;
75
76 fn from_str(extension: &str) -> Result<Self, Self::Err> {
77 Self::try_from(extension)
78 }
79}
80
81#[derive(Debug, Clone, Eq, PartialEq)]
82pub enum ParseError {
83 InvalidExtension(String),
84}
85
86impl fmt::Display for ParseError {
87 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88 match self {
89 ParseError::InvalidExtension(extension) => {
90 write!(f, "Invalid archive extension: {extension}")
91 }
92 }
93 }
94}
95
96#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
98pub struct ZstdConfig {
99 pub compression_level: i32,
101}
102
103#[cfg(test)]
104mod tests {
105 use {super::*, std::iter::zip};
106 const INVALID_EXTENSION: &str = "zip";
107
108 #[test]
109 fn test_extension() {
110 assert_eq!(ArchiveFormat::TarBzip2.extension(), TAR_BZIP2_EXTENSION);
111 assert_eq!(ArchiveFormat::TarGzip.extension(), TAR_GZIP_EXTENSION);
112 assert_eq!(
113 ArchiveFormat::TarZstd {
114 config: ZstdConfig::default(),
115 }
116 .extension(),
117 TAR_ZSTD_EXTENSION
118 );
119 assert_eq!(ArchiveFormat::TarLz4.extension(), TAR_LZ4_EXTENSION);
120 assert_eq!(ArchiveFormat::Tar.extension(), TAR_EXTENSION);
121 }
122
123 #[test]
124 fn test_try_from() {
125 assert_eq!(
126 ArchiveFormat::try_from(TAR_BZIP2_EXTENSION),
127 Ok(ArchiveFormat::TarBzip2)
128 );
129 assert_eq!(
130 ArchiveFormat::try_from(TAR_GZIP_EXTENSION),
131 Ok(ArchiveFormat::TarGzip)
132 );
133 assert_eq!(
134 ArchiveFormat::try_from(TAR_ZSTD_EXTENSION),
135 Ok(ArchiveFormat::TarZstd {
136 config: ZstdConfig::default(),
137 })
138 );
139 assert_eq!(
140 ArchiveFormat::try_from(TAR_LZ4_EXTENSION),
141 Ok(ArchiveFormat::TarLz4)
142 );
143 assert_eq!(
144 ArchiveFormat::try_from(TAR_EXTENSION),
145 Ok(ArchiveFormat::Tar)
146 );
147 assert_eq!(
148 ArchiveFormat::try_from(INVALID_EXTENSION),
149 Err(ParseError::InvalidExtension(INVALID_EXTENSION.to_string()))
150 );
151 }
152
153 #[test]
154 fn test_from_str() {
155 assert_eq!(
156 ArchiveFormat::from_str(TAR_BZIP2_EXTENSION),
157 Ok(ArchiveFormat::TarBzip2)
158 );
159 assert_eq!(
160 ArchiveFormat::from_str(TAR_GZIP_EXTENSION),
161 Ok(ArchiveFormat::TarGzip)
162 );
163 assert_eq!(
164 ArchiveFormat::from_str(TAR_ZSTD_EXTENSION),
165 Ok(ArchiveFormat::TarZstd {
166 config: ZstdConfig::default(),
167 })
168 );
169 assert_eq!(
170 ArchiveFormat::from_str(TAR_LZ4_EXTENSION),
171 Ok(ArchiveFormat::TarLz4)
172 );
173 assert_eq!(
174 ArchiveFormat::from_str(TAR_EXTENSION),
175 Ok(ArchiveFormat::Tar)
176 );
177 assert_eq!(
178 ArchiveFormat::from_str(INVALID_EXTENSION),
179 Err(ParseError::InvalidExtension(INVALID_EXTENSION.to_string()))
180 );
181 }
182
183 #[test]
184 fn test_from_cli_arg() {
185 let golden = [
186 Some(ArchiveFormat::TarZstd {
187 config: ZstdConfig::default(),
188 }),
189 Some(ArchiveFormat::TarLz4),
190 ];
191
192 for (arg, expected) in zip(SUPPORTED_ARCHIVE_COMPRESSION.iter(), golden.into_iter()) {
193 assert_eq!(ArchiveFormat::from_cli_arg(arg), expected);
194 }
195
196 assert_eq!(ArchiveFormat::from_cli_arg("bad"), None);
197 }
198}