Skip to main content

ed_journals/modules/fs/models/common/
different_file.rs

1use crate::fs::common::LogFile;
2use crate::fs::{LogFSError, Unblocker};
3use crate::io::LogIOError;
4use crate::logs::LogEvent;
5use serde::de::DeserializeOwned;
6use std::path::{Path, PathBuf};
7use std::sync::Arc;
8
9/// Holds a [LogFile] which is changed when [DifferentFile::maybe_switch] is called with a different
10/// path than the current one. Calling [Iterator::next] on this type will call the inner file or
11/// return [None] if the file is not yet loaded.
12pub struct DifferentFile<R = LogEvent>
13where
14    R: DeserializeOwned,
15{
16    current_path: Option<PathBuf>,
17    current_file: Option<LogFile<R>>,
18    unblocker: Arc<dyn Unblocker>,
19}
20
21impl DifferentFile {
22    pub fn new(blocker: impl Into<Arc<dyn Unblocker>>) -> DifferentFile {
23        DifferentFile::new_typed::<LogEvent>(blocker)
24    }
25
26    pub fn new_raw(blocker: impl Into<Arc<dyn Unblocker>>) -> DifferentFile<serde_json::Value> {
27        DifferentFile::new_typed::<serde_json::Value>(blocker)
28    }
29
30    pub fn new_typed<R>(blocker: impl Into<Arc<dyn Unblocker>>) -> DifferentFile<R>
31    where
32        R: DeserializeOwned,
33    {
34        DifferentFile {
35            current_path: None,
36            current_file: None,
37            unblocker: blocker.into(),
38        }
39    }
40}
41
42impl<R> DifferentFile<R>
43where
44    R: DeserializeOwned,
45{
46    /// If the provided path is different from the path of the current file, then a new file is
47    /// opened using the provided path and replaces the current file.
48    pub fn maybe_switch<P: AsRef<Path>>(&mut self, path: P) -> Result<bool, LogFSError> {
49        let path = path.as_ref();
50
51        if self.current_path.is_none() || self.current_path.as_ref().is_some_and(|v| v != path) {
52            self.current_path = Some(path.to_path_buf());
53            self.current_file = Some(LogFile::new_typed::<R, _>(path, self.unblocker.clone())?);
54
55            return Ok(true);
56        }
57
58        Ok(false)
59    }
60}
61
62impl<R> Iterator for DifferentFile<R>
63where
64    R: DeserializeOwned,
65{
66    type Item = Result<R, LogIOError>;
67
68    fn next(&mut self) -> Option<Self::Item> {
69        self.current_file.as_mut()?.next()
70    }
71}