use std::{fmt::Debug, ops::Add, time::SystemTime};
pub trait Resource : Debug {
fn timestamp(&self) -> Option<SystemTime>;
fn mk_from<F, R, S>(&self, description: &str, src: S, by: F)
where R:Resource, S:AsResource<R>, F: FnOnce() -> ()
{
let src = src.as_res();
let target_time = self.timestamp();
if target_time == None || src.timestamp() > target_time {
println!("Building: {:?} from {:?}: {}", self, src, description);
by();
}
}
fn mk_from_result<E, F, R, S>(&self, description: &str, src: S, by: F) -> Result<(), E>
where R:Resource, S:AsRef<R>, F: FnOnce() -> Result<(), E>
{
let src = src.as_ref();
let target_time = self.timestamp();
if target_time == None || src.timestamp() > target_time {
println!("Building: {:?} from {:?}: {}", self, src, description);
return by()
}
Ok(())
}
}
pub trait AsResource<R> {
fn as_res(&self) -> &R;
}
impl<R> AsResource<R> for R where R:Resource {
fn as_res(&self) -> &R {
&self
}
}
impl<R> AsResource<R> for &R where R:Resource {
fn as_res(&self) -> &R {
self
}
}
impl<R> Resource for Vec<R>
where R:Resource
{
fn timestamp(&self) -> Option<SystemTime> {
timestamp(self.iter())
}
}
pub fn timestamp<T: AsResource<R>, R: Resource>(iter: impl Iterator<Item=T>) -> Option<SystemTime> {
iter.fold(None, |result, entry| {
let timestamp = entry.as_res().timestamp();
if timestamp > result {
return timestamp;
}
result
})
}
#[derive(Debug,Clone)]
pub struct Set<T> {
items: Vec<T>
}
impl<R> Add<&R> for Set<R> where R: Clone {
type Output = Set<R>;
fn add(mut self, rhs: &R) -> Self::Output {
self.items.push(rhs.clone());
self
}
}
impl<R> Add<R> for Set<R> {
type Output = Set<R>;
fn add(mut self, rhs: R) -> Self::Output {
self.items.push(rhs);
self
}
}
impl<T> AsRef<Set<T>> for Set<T> {
fn as_ref(&self) -> &Set<T> {
self
}
}
impl<T> From<Vec<T>> for Set<T> {
fn from(val: Vec<T>) -> Self {
Set { items: val }
}
}
impl<T> IntoIterator for Set<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
impl<R> Resource for Set<R> where R:Resource {
fn timestamp(&self) -> Option<SystemTime> {
self.items.timestamp()
}
}