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