1use std::{fmt::Display, path::Path, str::FromStr};
3
4use serde_with::DeserializeFromStr;
5use sketching::tracing::warn;
6
7#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, DeserializeFromStr)]
8pub enum BackupCompression {
10 NoCompression,
11 #[default]
12 Gzip,
13}
14
15impl BackupCompression {
16 pub fn suffix(&self) -> &'static str {
17 match self {
18 BackupCompression::NoCompression => "",
19 BackupCompression::Gzip => ".gz",
20 }
21 }
22
23 pub fn identify_file(filepath: &Path) -> Self {
24 let filename = filepath.file_name().and_then(|s| s.to_str()).unwrap_or("");
25 if filename.ends_with(".gz") {
26 BackupCompression::Gzip
27 } else {
28 BackupCompression::NoCompression
29 }
30 }
31}
32
33impl Display for BackupCompression {
34 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
35 match self {
36 BackupCompression::NoCompression => write!(f, "No Compression"),
37 BackupCompression::Gzip => write!(f, "Gzip"),
38 }
39 }
40}
41
42impl From<Option<String>> for BackupCompression {
43 fn from(opt: Option<String>) -> Self {
44 match opt {
45 Some(s) => BackupCompression::from(s),
46 None => BackupCompression::default(),
47 }
48 }
49}
50
51impl From<String> for BackupCompression {
52 fn from(s: String) -> Self {
53 match s.to_lowercase().as_str() {
54 "gzip" => BackupCompression::Gzip,
55 "none" | "nocompression" => BackupCompression::NoCompression,
56 _ => {
57 warn!(
58 "Unknown compression type '{}', should be one of nocompression, gzip - defaulting to {}",
59 s,
60 BackupCompression::default()
61 );
62 BackupCompression::default()
63 }
64 }
65 }
66}
67
68impl FromStr for BackupCompression {
69 type Err = &'static str;
70
71 fn from_str(s: &str) -> Result<Self, Self::Err> {
72 Ok(s.to_string().into())
73 }
74}
75
76#[test]
77
78fn test_backup_compression_identify() {
79 let gzip_path = Path::new("/var/lib/kanidm/backups/backup-2024-01-01.tar.gz");
80 let no_comp_path = Path::new("/var/lib/kanidm/backups/backup-2024-01-01.tar");
81
82 assert_eq!(
83 BackupCompression::identify_file(gzip_path),
84 BackupCompression::Gzip
85 );
86 assert_eq!(
87 BackupCompression::identify_file(no_comp_path),
88 BackupCompression::NoCompression
89 );
90
91 for (input, expected) in [
92 (vec!["gzip", "Gzip", "GzIp"], BackupCompression::Gzip),
93 (
94 vec!["none", "NoNe", "nocompression", "NoCompression"],
95 BackupCompression::NoCompression,
96 ),
97 ] {
98 for i in input {
99 assert_eq!(
100 BackupCompression::from_str(i).expect("Threw an error?"),
101 expected
102 );
103 }
104 }
105}