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,
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 "lz4" => Some(ArchiveFormat::TarLz4),
47 _ => None,
48 }
49 }
50}
51
52impl TryFrom<&str> for ArchiveFormat {
55 type Error = ParseError;
56
57 fn try_from(extension: &str) -> Result<Self, Self::Error> {
58 match extension {
59 TAR_BZIP2_EXTENSION => Ok(ArchiveFormat::TarBzip2),
60 TAR_GZIP_EXTENSION => Ok(ArchiveFormat::TarGzip),
61 TAR_ZSTD_EXTENSION => Ok(ArchiveFormat::TarZstd),
62 TAR_LZ4_EXTENSION => Ok(ArchiveFormat::TarLz4),
63 TAR_EXTENSION => Ok(ArchiveFormat::Tar),
64 _ => Err(ParseError::InvalidExtension(extension.to_string())),
65 }
66 }
67}
68
69impl FromStr for ArchiveFormat {
70 type Err = ParseError;
71
72 fn from_str(extension: &str) -> Result<Self, Self::Err> {
73 Self::try_from(extension)
74 }
75}
76
77#[derive(Debug, Clone, Eq, PartialEq)]
78pub enum ParseError {
79 InvalidExtension(String),
80}
81
82impl fmt::Display for ParseError {
83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 match self {
85 ParseError::InvalidExtension(extension) => {
86 write!(f, "Invalid archive extension: {extension}")
87 }
88 }
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use {super::*, std::iter::zip};
95 const INVALID_EXTENSION: &str = "zip";
96
97 #[test]
98 fn test_extension() {
99 assert_eq!(ArchiveFormat::TarBzip2.extension(), TAR_BZIP2_EXTENSION);
100 assert_eq!(ArchiveFormat::TarGzip.extension(), TAR_GZIP_EXTENSION);
101 assert_eq!(ArchiveFormat::TarZstd.extension(), TAR_ZSTD_EXTENSION);
102 assert_eq!(ArchiveFormat::TarLz4.extension(), TAR_LZ4_EXTENSION);
103 assert_eq!(ArchiveFormat::Tar.extension(), TAR_EXTENSION);
104 }
105
106 #[test]
107 fn test_try_from() {
108 assert_eq!(
109 ArchiveFormat::try_from(TAR_BZIP2_EXTENSION),
110 Ok(ArchiveFormat::TarBzip2)
111 );
112 assert_eq!(
113 ArchiveFormat::try_from(TAR_GZIP_EXTENSION),
114 Ok(ArchiveFormat::TarGzip)
115 );
116 assert_eq!(
117 ArchiveFormat::try_from(TAR_ZSTD_EXTENSION),
118 Ok(ArchiveFormat::TarZstd)
119 );
120 assert_eq!(
121 ArchiveFormat::try_from(TAR_LZ4_EXTENSION),
122 Ok(ArchiveFormat::TarLz4)
123 );
124 assert_eq!(
125 ArchiveFormat::try_from(TAR_EXTENSION),
126 Ok(ArchiveFormat::Tar)
127 );
128 assert_eq!(
129 ArchiveFormat::try_from(INVALID_EXTENSION),
130 Err(ParseError::InvalidExtension(INVALID_EXTENSION.to_string()))
131 );
132 }
133
134 #[test]
135 fn test_from_str() {
136 assert_eq!(
137 ArchiveFormat::from_str(TAR_BZIP2_EXTENSION),
138 Ok(ArchiveFormat::TarBzip2)
139 );
140 assert_eq!(
141 ArchiveFormat::from_str(TAR_GZIP_EXTENSION),
142 Ok(ArchiveFormat::TarGzip)
143 );
144 assert_eq!(
145 ArchiveFormat::from_str(TAR_ZSTD_EXTENSION),
146 Ok(ArchiveFormat::TarZstd)
147 );
148 assert_eq!(
149 ArchiveFormat::from_str(TAR_LZ4_EXTENSION),
150 Ok(ArchiveFormat::TarLz4)
151 );
152 assert_eq!(
153 ArchiveFormat::from_str(TAR_EXTENSION),
154 Ok(ArchiveFormat::Tar)
155 );
156 assert_eq!(
157 ArchiveFormat::from_str(INVALID_EXTENSION),
158 Err(ParseError::InvalidExtension(INVALID_EXTENSION.to_string()))
159 );
160 }
161
162 #[test]
163 fn test_from_cli_arg() {
164 let golden = [Some(ArchiveFormat::TarZstd), Some(ArchiveFormat::TarLz4)];
165
166 for (arg, expected) in zip(SUPPORTED_ARCHIVE_COMPRESSION.iter(), golden.into_iter()) {
167 assert_eq!(ArchiveFormat::from_cli_arg(arg), expected);
168 }
169
170 assert_eq!(ArchiveFormat::from_cli_arg("bad"), None);
171 }
172}