use std::ops::{Deref, DerefMut, Range};
use crate::math::Lerp;
use crate::{Node, NodeBuilder, NodeDecl, RenderContext};
use anyhow::Result;
mod imap;
mod lerp;
mod map;
mod map_range;
#[derive(Debug)]
pub struct Buffer<E> {
data: Box<[E]>,
}
impl<E> Buffer<E> {
pub fn from_generator<F, R>(size: usize, generator: F) -> Self
where
F: Fn(usize) -> R,
R: Into<E>,
{
let data = (0..size).map(generator).map(Into::into).collect();
return Self {
data,
};
}
pub fn from_value(size: usize, value: impl Into<E>) -> Self
where E: Copy {
let value = value.into();
let data = (0..size).map(|_| value).collect();
return Self {
data,
};
}
pub fn size(&self) -> usize {
return self.data.len();
}
pub fn get(&self, index: usize) -> &E {
return &self.data[index % self.data.len()];
}
pub fn set(&mut self, index: usize, value: E) {
self.data[index % self.data.len()] = value;
}
pub fn iter(&self) -> impl Iterator<Item = &E> {
return self.data.iter();
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut E> {
return self.data.iter_mut();
}
pub fn update(&mut self, f: impl Fn(usize, &E) -> E) {
self.data.iter_mut().enumerate().for_each(|(i, e)| *e = f(i, e));
}
pub fn try_update(&mut self, f: impl Fn(usize, &E) -> Result<E>) -> Result<()> {
self.data = self.data.iter().enumerate().map(|(i, e)| f(i, e)).collect::<Result<_>>()?;
return Ok(());
}
pub fn blit_from(&mut self, source: impl BufferReader<Element = E>) {
assert_eq!(self.size(), source.size());
for i in 0..self.size() {
self.data[i] = source.get(i);
}
}
}
impl<E> Buffer<E>
where E: Default
{
pub fn with_default(size: usize) -> Self {
return Self::from_generator(size, |_| E::default());
}
}
impl<E> Deref for Buffer<E> {
type Target = [E];
fn deref(&self) -> &Self::Target {
return &self.data;
}
}
impl<E> DerefMut for Buffer<E> {
fn deref_mut(&mut self) -> &mut Self::Target {
return &mut self.data;
}
}
impl<E> AsRef<[E]> for Buffer<E> {
fn as_ref(&self) -> &[E] {
return self.data.as_ref();
}
}
impl<E> AsMut<[E]> for Buffer<E> {
fn as_mut(&mut self) -> &mut [E] {
return self.data.as_mut();
}
}
pub trait BufferReader {
type Element;
fn get(&self, index: usize) -> Self::Element;
fn size(&self) -> usize;
fn iter(&self) -> impl Iterator<Item = Self::Element>
where Self: Sized {
return (0..self.size()).map(|i| self.get(i));
}
fn map<R, F>(&self, f: F) -> impl BufferReader<Element = R>
where
Self: Sized,
F: Fn(Self::Element) -> R,
{
return map::Map::new(self, f);
}
fn imap<R, F>(&self, f: F) -> impl BufferReader<Element = R>
where
Self: Sized,
F: Fn(usize, Self::Element) -> R,
{
return imap::IMap::new(self, f);
}
fn map_range<F>(&self, range: &Range<usize>, f: F) -> impl BufferReader<Element = Self::Element>
where
Self: Sized,
F: Fn(Self::Element) -> Self::Element,
{
return map_range::MapRange::new(self, range, f);
}
fn lerp<R>(&self, other: &R, i: f32) -> impl BufferReader<Element = Self::Element>
where
Self: Sized,
Self::Element: Lerp,
R: BufferReader<Element = Self::Element>,
{
return lerp::Lerp::new(self, other, i);
}
fn slice(&self, range: Range<usize>) -> Slice<'_, Self::Element>
where Self: Sized {
return Slice {
inner: self,
range,
};
}
}
impl<E> BufferReader for Buffer<E>
where E: Copy
{
type Element = E;
fn get(&self, index: usize) -> Self::Element {
return *Buffer::get(self, index);
}
fn size(&self) -> usize {
return Buffer::size(self);
}
}
impl<E> BufferReader for &Buffer<E>
where E: Copy
{
type Element = E;
fn get(&self, index: usize) -> Self::Element {
return *Buffer::get(self, index);
}
fn size(&self) -> usize {
return Buffer::size(self);
}
}
pub struct Slice<'a, E> {
inner: &'a dyn BufferReader<Element = E>,
range: Range<usize>,
}
impl<E> BufferReader for Slice<'_, E> {
type Element = E;
fn get(&self, index: usize) -> Self::Element {
return self.inner.get(index + self.range.start);
}
fn size(&self) -> usize {
return self.range.end - self.range.start;
}
}
impl<E> NodeDecl for Buffer<E>
where E: Default + Copy
{
const KIND: &'static str = "buffer";
type Node = Self;
async fn materialize(self, _builder: &mut NodeBuilder<'_>) -> Result<Self::Node> {
return Ok(self);
}
}
impl<E> Node for Buffer<E>
where E: Default + Copy
{
type Element = E;
fn update(&mut self, _ctx: &RenderContext, out: &mut Buffer<Self::Element>) -> Result<()> {
out.blit_from(&*self);
return Ok(());
}
}