use color_eyre::Result;
pub trait UI<Cushion: Send + Sync + 'static> {
type Context;
fn run(
&self,
batcher: crate::launcher::batcher::Batcher<Cushion, Self::Context>,
) -> impl std::future::Future<Output = Result<Option<Cushion>>> + Send;
}
#[derive(Debug, Clone)]
pub struct Buffer<T> {
vec: Vec<T>,
}
impl<T> From<Vec<T>> for Buffer<T> {
fn from(vec: Vec<T>) -> Self {
Self { vec }
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct Position(pub usize);
impl Position {
pub fn reset(&mut self) {
self.0 = 0;
}
}
impl<T> Default for Buffer<T> {
fn default() -> Self {
Self { vec: vec![] }
}
}
impl<T> Buffer<T> {
#[inline]
pub(crate) fn reset(&mut self) {
*self = Self::default();
}
#[inline]
pub(crate) fn into_inner(self) -> Vec<T> {
self.vec
}
#[inline]
pub(crate) fn as_mut(&mut self) -> &mut Vec<T> {
&mut self.vec
}
#[inline]
pub fn len(&self) -> usize {
self.vec.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.vec.is_empty()
}
#[inline]
pub fn push(&mut self, value: T) {
self.vec.push(value);
}
#[allow(clippy::should_implement_trait)]
#[inline]
pub fn next(&self, pos: &mut Position) -> Option<&T> {
pos.0 += 1;
self.vec.get(pos.0 - 1)
}
#[inline]
pub fn has_next(&self, pos: &Position) -> bool {
pos.0 + 1 < self.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buffer() -> Result<(), Box<dyn std::error::Error>> {
let mut pos = Position::default();
let buf = {
let mut buf = Buffer::default();
let v = buf.as_mut();
v.push((1, 1));
v.push((2, 2));
dbg!(v);
buf
};
assert_eq!(buf.next(&mut pos), Some((1u32, 1)).as_ref());
assert_eq!(buf.next(&mut pos), Some((2u32, 2)).as_ref());
assert_eq!(buf.next(&mut pos), None);
pos.reset();
assert_eq!(buf.next(&mut pos), Some((1u32, 1)).as_ref());
assert_eq!(buf.next(&mut pos), Some((2u32, 2)).as_ref());
assert_eq!(buf.next(&mut pos), None);
Ok(())
}
}