use core::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
use pin_project::pin_project;
pub struct Grant<'a, T> {
handle: &'a mut T,
count: usize,
}
impl<'a, T> Future for Grant<'a, T>
where
T: View,
{
type Output = Result<(), T::Error>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let count = self.count;
Pin::new(&mut self.handle).poll_grant(cx, count)
}
}
pub trait View: Sized + Unpin {
type Item;
type Error: core::fmt::Debug;
fn view(&self) -> &[Self::Item];
fn poll_grant(
self: Pin<&mut Self>,
cx: &mut Context,
count: usize,
) -> Poll<Result<(), Self::Error>>;
fn release(&mut self, count: usize);
fn grant(&mut self, count: usize) -> Grant<'_, Self> {
Grant {
handle: self,
count,
}
}
fn blocking_grant(&mut self, count: usize) -> Result<(), Self::Error> {
futures::executor::block_on(self.grant(count))
}
fn map_error<E, F>(self, f: F) -> MapError<Self, E, F>
where
F: Fn(Self::Error) -> E,
{
MapError {
view: self,
map: f,
_error: core::marker::PhantomData,
}
}
}
impl<S: View> View for &mut S {
type Item = S::Item;
type Error = S::Error;
fn view(&self) -> &[Self::Item] {
View::view(*self)
}
fn poll_grant(
mut self: Pin<&mut Self>,
cx: &mut Context,
count: usize,
) -> Poll<Result<(), Self::Error>> {
S::poll_grant(Pin::new(&mut **self), cx, count)
}
fn release(&mut self, count: usize) {
S::release(self, count)
}
}
pub trait ViewMut: View {
fn view_mut(&mut self) -> &mut [Self::Item];
}
impl<S: ViewMut> ViewMut for &mut S {
fn view_mut(&mut self) -> &mut [Self::Item] {
ViewMut::view_mut(*self)
}
}
#[pin_project]
#[derive(Debug)]
pub struct MapError<V, E, F> {
#[pin]
view: V,
map: F,
_error: core::marker::PhantomData<E>,
}
impl<V, E, F> MapError<V, E, F> {
pub fn into_inner(self) -> V {
self.view
}
}
impl<V, E, F> View for MapError<V, E, F>
where
V: View,
E: core::fmt::Debug,
F: Fn(V::Error) -> E,
{
type Item = V::Item;
type Error = E;
fn view(&self) -> &[Self::Item] {
self.view.view()
}
fn poll_grant(
self: Pin<&mut Self>,
cx: &mut Context,
count: usize,
) -> Poll<Result<(), Self::Error>> {
let pinned = self.project();
let f = pinned.map;
pinned.view.poll_grant(cx, count).map(|r| r.map_err(f))
}
fn release(&mut self, count: usize) {
self.view.release(count)
}
}
impl<V, E, F> ViewMut for MapError<V, E, F>
where
V: ViewMut,
E: core::fmt::Debug,
F: Fn(V::Error) -> E,
{
fn view_mut(&mut self) -> &mut [Self::Item] {
self.view.view_mut()
}
}
impl<V, E, F> Copy for MapError<V, E, F>
where
V: Copy,
F: Copy,
{
}
impl<V, E, F> Clone for MapError<V, E, F>
where
V: Clone,
F: Clone,
{
fn clone(&self) -> Self {
Self {
view: self.view.clone(),
map: self.map.clone(),
_error: core::marker::PhantomData,
}
}
}
impl<V, E, F> core::hash::Hash for MapError<V, E, F>
where
V: core::hash::Hash,
F: core::hash::Hash,
{
fn hash<H>(&self, state: &mut H)
where
H: core::hash::Hasher,
{
self.view.hash(state);
self.map.hash(state);
}
}