nunc 0.2.0

WIP: time tracking application
Documentation
pub mod format;
#[macro_use]
pub mod serde;

use std::iter::Map;

use greg::Point;

/// An [`Iterator`] adapter that turns a `(`[`Point`]`, T)` [`Iterator`] into a `(`[`Point`]`, Option<`[`Point`]`>, T)` [`Iterator`]
///
/// For iterating over time-series data where each entry / item is associated with a starting [`Point`] and ends when the next entry begins.
/// This struct pre-fetches the next item in the underlying [`Iterator`] in order to include the end [`Point`] for each iteration.
///
/// The last item returned doesn't have an end [`Point`], hence `Option<`[`Point`]`>`.
pub struct TryFrames<I, T> {
	iter: I,
	current: Option<(Point, T)>
}

fn deref_point<T>(p_t: &(Point, T)) -> (Point, &T) {
	let (p, t) = p_t;
	(*p, t)
}

impl<I: Iterator<Item = (Point, T)>, T> TryFrames<I, T> {
	pub fn new(mut iter: I) -> Self {
		let current = iter.next();
		Self {iter, current}
	}
}

impl TryFrames<(), ()> {
	#[allow(clippy::type_complexity)]
	pub fn new_ref<'t, T, R: Iterator<Item = &'t (Point, T)>>(ref_iter: R)
		-> TryFrames<Map<R, impl Fn(&(Point, T)) -> (Point, &T)>, &'t T>
	{
		let mut iter = ref_iter.map(deref_point);
		let current = iter.next();
		TryFrames {iter, current}
	}
}

impl<I: Iterator<Item = (Point, T)>, T> Iterator for TryFrames<I, T> {
	type Item = (Point, Option<Point>, T);
	fn next(&mut self) -> Option<Self::Item> {
		match (self.current.take(), self.iter.next()) {
			(Some((curr_p, curr_item)), Some(next @ (next_p, _))) => {
				self.current = Some(next);
				Some((curr_p, Some(next_p), curr_item))
			},
			(Some((last_p, last_off)), None) => Some((last_p, None, last_off)),
			(None, _) => None
		}
	}
}
impl<I, T> ExactSizeIterator for TryFrames<I, T>
	where I: ExactSizeIterator<Item = (Point, T)>
{
	fn len(&self) -> usize {self.iter.len() + self.current.iter().count()}
}