diff options
author | Toby Vincent <tobyv13@gmail.com> | 2023-04-28 17:32:24 -0500 |
---|---|---|
committer | Toby Vincent <tobyv13@gmail.com> | 2023-04-28 17:32:24 -0500 |
commit | 589cd987217755e1da7acbc304c373a75a9f7db5 (patch) | |
tree | 2730a697e4f7b2f779fcd96b0452719cc67f36e3 /src/project.rs | |
parent | a98b50667bc6a11e4b8be464969adc14601e9e78 (diff) |
refactor: simplify logic and clean up dep.
Diffstat (limited to 'src/project.rs')
-rw-r--r-- | src/project.rs | 82 |
1 files changed, 57 insertions, 25 deletions
diff --git a/src/project.rs b/src/project.rs index 26f0a8b..2b3e028 100644 --- a/src/project.rs +++ b/src/project.rs @@ -1,47 +1,79 @@ -use std::{path::PathBuf, time::Duration}; +use std::{ + ops::{Deref, DerefMut}, + path::PathBuf, + time::{Duration, SystemTime}, +}; + +use tracing::warn; pub mod path; #[cfg(feature = "git")] pub mod git; -pub type ProjectParserGroup = Vec<Box<dyn ProjectParser>>; - pub trait ProjectParser { - fn parse(&self, path_buf: PathBuf) -> Option<ProjectItem>; + fn parse(&self, path_buf: PathBuf) -> Result<Project, Box<dyn std::error::Error>>; } -impl ProjectParser for ProjectParserGroup { - fn parse(&self, path_buf: std::path::PathBuf) -> Option<ProjectItem> { - self.iter().find_map(|p| p.parse(path_buf.to_owned())) +#[derive(Default)] +pub struct ProjectParserGroup { + pub parsers: Vec<Box<dyn ProjectParser>>, +} + +impl ProjectParserGroup { + pub fn new() -> Self { + Self::default() + } + + pub fn parse(&self, path_buf: std::path::PathBuf) -> Option<Project> { + if self.parsers.is_empty() { + return path_buf.try_into().ok(); + } + + self.iter() + .map(|p| p.parse(path_buf.to_owned())) + .inspect(|res| { + if let Err(err) = res { + warn!(%err, "Parser failed to match"); + } + }) + .flatten() + .reduce(|max, p| p.max(max)) } } -pub type ProjectItem = Box<dyn Project>; +impl Deref for ProjectParserGroup { + type Target = Vec<Box<dyn ProjectParser>>; -pub trait Project: Timestamp { - fn to_path_buf(&self) -> &PathBuf; + fn deref(&self) -> &Self::Target { + &self.parsers + } } -impl<T> Project for T -where - T: Timestamp, - T: AsRef<PathBuf>, -{ - fn to_path_buf(&self) -> &PathBuf { - self.as_ref() +impl DerefMut for ProjectParserGroup { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.parsers } } -pub trait Timestamp { - fn timestamp(&self) -> &Duration; +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Project { + pub timestamp: Duration, + pub worktree: PathBuf, } -impl<T> Timestamp for T -where - T: AsRef<Duration>, -{ - fn timestamp(&self) -> &Duration { - self.as_ref() +impl TryFrom<PathBuf> for Project { + type Error = std::io::Error; + + fn try_from(value: PathBuf) -> Result<Self, Self::Error> { + let timestamp = value + .metadata()? + .modified()? + .duration_since(SystemTime::UNIX_EPOCH) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err.to_string()))?; + Ok(Self { + worktree: value, + timestamp, + }) } } |