ed_journals/modules/io/models/
log_path.rs1use crate::modules::io::LogIOError;
2use chrono::NaiveDateTime;
3use lazy_static::lazy_static;
4use regex::Regex;
5use std::cmp::Ordering;
6use std::path::{Path, PathBuf};
7
8#[derive(Debug, Clone)]
10pub struct LogPath {
11 pub path: PathBuf,
12 pub timestamp: NaiveDateTime,
13 pub part: u8,
14}
15
16#[cfg(not(feature = "legacy"))]
17type RegexList = [(Regex, &'static str); 1];
18
19#[cfg(feature = "legacy")]
20type RegexList = [(Regex, &'static str); 2];
21
22lazy_static! {
23 static ref FILE_NAME_REGEXES: RegexList = [
24 (Regex::new(r"Journal\.(\d{4}-\d{2}-\d{2}T\d+)\.(\d{2})\.log").unwrap(), "%Y-%m-%dT%H%M%S"),
26
27 #[cfg(feature = "legacy")]
29 (Regex::new(r"Journal\.(\d{12})\.(\d{2})\.log").unwrap(), "%y%m%d%H%M%S"),
30 ];
31}
32
33impl TryFrom<&Path> for LogPath {
34 type Error = LogIOError;
35
36 fn try_from(value: &Path) -> Result<Self, Self::Error> {
37 let file_name = value
38 .file_name()
39 .ok_or(LogIOError::MissingFileName)?
40 .to_str()
41 .ok_or(LogIOError::FailedToRepresentOsString)?;
42
43 for (regex, format) in FILE_NAME_REGEXES.iter() {
44 let Some(captures) = regex.captures(file_name) else {
45 continue;
46 };
47
48 let timestamp_str = captures
49 .get(1)
50 .expect("Regex should have already matched")
51 .as_str();
52
53 let timestamp = NaiveDateTime::parse_from_str(timestamp_str, format)
54 .map_err(LogIOError::FailedToParseLogTime)?;
55
56 let part = captures
57 .get(2)
58 .expect("Regex should have already matched")
59 .as_str()
60 .parse()
61 .map_err(LogIOError::FailedToParsePart)?;
62
63 return Ok(LogPath {
64 path: value.to_path_buf(),
65 timestamp,
66 part,
67 });
68 }
69
70 Err(LogIOError::IncorrectFileName)
71 }
72}
73
74impl AsRef<Path> for LogPath {
75 fn as_ref(&self) -> &Path {
76 self.path.as_path()
77 }
78}
79
80impl From<LogPath> for PathBuf {
81 fn from(val: LogPath) -> Self {
82 val.path
83 }
84}
85
86impl Eq for LogPath {}
87
88impl PartialEq for LogPath {
89 fn eq(&self, other: &Self) -> bool {
90 self.path.eq(&other.path)
91 }
92}
93
94impl PartialOrd for LogPath {
95 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
96 Some(self.cmp(other))
97 }
98}
99
100impl Ord for LogPath {
101 fn cmp(&self, other: &Self) -> Ordering {
102 self.timestamp
103 .cmp(&other.timestamp)
104 .then(self.part.cmp(&other.part))
105 }
106}