Skip to content

Commit 3b06f87

Browse files
initial commit
0 parents  commit 3b06f87

File tree

8 files changed

+758
-0
lines changed

8 files changed

+758
-0
lines changed

.github/workflows/build.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/checkout@v1
14+
- name: Install dependencies
15+
run: |
16+
rustup default stable
17+
rustup update
18+
- name: Build
19+
run: cargo build
20+
- name: Build documentation
21+
run: |
22+
cargo rustdoc
23+
echo "<!DOCTYPE html><html><head><script>window.location.replace(\"/protocol/protocol\");</script></head></html>" > target/doc/index.html
24+
- name: Deploy documentation
25+
uses: JamesIves/[email protected]
26+
env:
27+
ACCESS_TOKEN: ${{ secrets.GH_PAT }}
28+
BASE_BRANCH: master
29+
BRANCH: gh-pages
30+
FOLDER: target/doc

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "protocol"
3+
version = "0.1.0"
4+
authors = ["Izzy Swart <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
void = { version = "1.0.2", default-features = false }
9+
futures = { version = "0.3.4" }

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Documentation](https://noocene.github.io/protocol)

src/lib.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#![no_std]
2+
3+
use core::{
4+
borrow::BorrowMut,
5+
pin::Pin,
6+
task::{Context, Poll},
7+
};
8+
use futures::ready;
9+
use void::Void;
10+
mod option;
11+
mod pass;
12+
mod result;
13+
pub use pass::Pass;
14+
15+
pub trait Future<C: ?Sized> {
16+
type Ok;
17+
type Error;
18+
19+
fn poll<R: BorrowMut<C>>(
20+
self: Pin<&mut Self>,
21+
cx: &mut Context,
22+
ctx: R,
23+
) -> Poll<Result<Self::Ok, Self::Error>>
24+
where
25+
Self: Sized;
26+
}
27+
28+
pub struct Ready<T> {
29+
data: Option<T>,
30+
}
31+
32+
impl<C: ?Sized, T: Unpin> Future<C> for Ready<T> {
33+
type Ok = T;
34+
type Error = Void;
35+
36+
fn poll<R: BorrowMut<C>>(
37+
mut self: Pin<&mut Self>,
38+
_: &mut Context,
39+
_: R,
40+
) -> Poll<Result<Self::Ok, Self::Error>>
41+
where
42+
Self: Sized,
43+
{
44+
Poll::Ready(Ok(self.data.take().expect("Ready polled after completion")))
45+
}
46+
}
47+
48+
pub fn ready<T>(data: T) -> Ready<T> {
49+
Ready { data: Some(data) }
50+
}
51+
52+
pub trait Unravel<C: ?Sized> {
53+
type Future: Future<C, Ok = ()>;
54+
55+
fn unravel(self) -> Self::Future;
56+
}
57+
58+
pub trait Coalesce<C: ?Sized>: Sized {
59+
type Future: Future<C, Ok = Self>;
60+
61+
fn coalesce() -> Self::Future;
62+
}
63+
64+
pub trait Dispatch<P> {
65+
type Handle;
66+
}
67+
68+
pub trait Fork<P>: Dispatch<P> {
69+
type Future: Future<Self, Ok = Self::Handle>;
70+
71+
fn fork(&mut self, item: P) -> Self::Future;
72+
}
73+
74+
pub trait Join<P>: Dispatch<P> {
75+
type Future: Future<Self, Ok = P>;
76+
77+
fn join(&mut self, handle: Self::Handle) -> Self::Future;
78+
}
79+
80+
pub trait Write<T> {
81+
type Error;
82+
83+
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
84+
fn write(self: Pin<&mut Self>, data: T) -> Result<(), Self::Error>;
85+
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
86+
}
87+
88+
impl<'a, T, U: Unpin + Write<T>> Write<T> for &'a mut U {
89+
type Error = U::Error;
90+
91+
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
92+
<U as Write<T>>::poll_ready(Pin::new(&mut **self), cx)
93+
}
94+
fn write(mut self: Pin<&mut Self>, data: T) -> Result<(), Self::Error> {
95+
<U as Write<T>>::write(Pin::new(&mut **self), data)
96+
}
97+
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
98+
<U as Write<T>>::poll_flush(Pin::new(&mut **self), cx)
99+
}
100+
}
101+
102+
pub trait Read<T> {
103+
type Error;
104+
105+
fn read(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<T, Self::Error>>;
106+
}

src/option.rs

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
use crate::{ready, Coalesce, Dispatch, Fork, Future, Join, Read, Unravel, Write};
2+
use core::{
3+
borrow::BorrowMut,
4+
mem::replace,
5+
pin::Pin,
6+
task::{Context, Poll},
7+
};
8+
9+
pub enum OptionUnravel<
10+
T: Unpin,
11+
C: ?Sized + Write<Option<<C as Dispatch<T>>::Handle>> + Fork<T> + Unpin,
12+
> {
13+
Some(T),
14+
None,
15+
Fork(C::Future),
16+
Write(C::Handle),
17+
Flush,
18+
Done,
19+
}
20+
21+
pub enum OptionCoalesce<
22+
T: Unpin,
23+
C: ?Sized + Read<Option<<C as Dispatch<T>>::Handle>> + Join<T> + Unpin,
24+
> {
25+
Read,
26+
Join(C::Future),
27+
Done,
28+
}
29+
30+
impl<T: Unpin, C: ?Sized + Write<Option<<C as Dispatch<T>>::Handle>> + Fork<T> + Unpin>
31+
From<Option<T>> for OptionUnravel<T, C>
32+
{
33+
fn from(data: Option<T>) -> Self {
34+
if let Some(data) = data {
35+
OptionUnravel::Some(data)
36+
} else {
37+
OptionUnravel::None
38+
}
39+
}
40+
}
41+
42+
#[derive(Debug)]
43+
pub enum OptionError<T, U> {
44+
Transport(T),
45+
Dispatch(U),
46+
}
47+
48+
impl<T: Unpin, C: ?Sized + Write<Option<<C as Dispatch<T>>::Handle>> + Fork<T> + Unpin> Future<C>
49+
for OptionUnravel<T, C>
50+
where
51+
C::Future: Unpin,
52+
C::Handle: Unpin,
53+
{
54+
type Ok = ();
55+
type Error = OptionError<C::Error, <C::Future as Future<C>>::Error>;
56+
57+
fn poll<R: BorrowMut<C>>(
58+
mut self: Pin<&mut Self>,
59+
cx: &mut Context,
60+
mut ctx: R,
61+
) -> Poll<Result<Self::Ok, Self::Error>>
62+
where
63+
Self: Sized,
64+
{
65+
let ctx = ctx.borrow_mut();
66+
67+
let this = &mut *self;
68+
69+
loop {
70+
match this {
71+
OptionUnravel::None => {
72+
let mut ctx = Pin::new(&mut *ctx);
73+
ready!(ctx.as_mut().poll_ready(cx)).map_err(OptionError::Transport)?;
74+
ctx.write(None).map_err(OptionError::Transport)?;
75+
replace(this, OptionUnravel::Flush);
76+
}
77+
OptionUnravel::Some(_) => {
78+
let data = replace(this, OptionUnravel::Done);
79+
if let OptionUnravel::Some(data) = data {
80+
replace(this, OptionUnravel::Fork(ctx.fork(data)));
81+
} else {
82+
panic!("invalid state in OptionUnravel Some")
83+
}
84+
}
85+
OptionUnravel::Fork(future) => {
86+
let handle = ready!(Pin::new(&mut *future).poll(cx, &mut *ctx))
87+
.map_err(OptionError::Dispatch)?;
88+
replace(this, OptionUnravel::Write(handle));
89+
}
90+
OptionUnravel::Write(_) => {
91+
let mut ctx = Pin::new(&mut *ctx);
92+
ready!(ctx.as_mut().poll_ready(cx)).map_err(OptionError::Transport)?;
93+
let data = replace(this, OptionUnravel::Done);
94+
if let OptionUnravel::Write(data) = data {
95+
ctx.write(Some(data)).map_err(OptionError::Transport)?;
96+
replace(this, OptionUnravel::Flush);
97+
} else {
98+
panic!("invalid state in OptionUnravel Write")
99+
}
100+
}
101+
OptionUnravel::Flush => {
102+
ready!(Pin::new(&mut *ctx).poll_ready(cx)).map_err(OptionError::Transport)?;
103+
replace(this, OptionUnravel::Done);
104+
return Poll::Ready(Ok(()));
105+
}
106+
OptionUnravel::Done => panic!("OptionUnravel polled after completion"),
107+
}
108+
}
109+
}
110+
}
111+
112+
impl<T: Unpin, C: ?Sized + Read<Option<<C as Dispatch<T>>::Handle>> + Join<T> + Unpin> Future<C>
113+
for OptionCoalesce<T, C>
114+
where
115+
C::Future: Unpin,
116+
C::Handle: Unpin,
117+
{
118+
type Ok = Option<T>;
119+
type Error = OptionError<C::Error, <C::Future as Future<C>>::Error>;
120+
121+
fn poll<R: BorrowMut<C>>(
122+
mut self: Pin<&mut Self>,
123+
cx: &mut Context,
124+
mut ctx: R,
125+
) -> Poll<Result<Self::Ok, Self::Error>>
126+
where
127+
Self: Sized,
128+
{
129+
let ctx = ctx.borrow_mut();
130+
131+
let this = &mut *self;
132+
133+
loop {
134+
match this {
135+
OptionCoalesce::Read => {
136+
let mut ctx = Pin::new(&mut *ctx);
137+
match ready!(ctx.as_mut().read(cx)).map_err(OptionError::Transport)? {
138+
None => {
139+
replace(this, OptionCoalesce::Done);
140+
return Poll::Ready(Ok(None));
141+
}
142+
Some(handle) => {
143+
replace(this, OptionCoalesce::Join(ctx.join(handle)));
144+
}
145+
}
146+
}
147+
OptionCoalesce::Join(future) => {
148+
return Poll::Ready(Ok(Some(
149+
ready!(Pin::new(future).poll(cx, &mut *ctx))
150+
.map_err(OptionError::Dispatch)?,
151+
)));
152+
}
153+
OptionCoalesce::Done => panic!("OptionUnravel polled after completion"),
154+
}
155+
}
156+
}
157+
}
158+
159+
impl<T: Unpin, C: ?Sized + Write<Option<<C as Dispatch<T>>::Handle>> + Fork<T> + Unpin> Unravel<C>
160+
for Option<T>
161+
where
162+
C::Future: Unpin,
163+
C::Handle: Unpin,
164+
{
165+
type Future = OptionUnravel<T, C>;
166+
167+
fn unravel(self) -> Self::Future {
168+
self.into()
169+
}
170+
}
171+
172+
impl<T: Unpin, C: ?Sized + Read<Option<<C as Dispatch<T>>::Handle>> + Join<T> + Unpin> Coalesce<C>
173+
for Option<T>
174+
where
175+
C::Future: Unpin,
176+
C::Handle: Unpin,
177+
{
178+
type Future = OptionCoalesce<T, C>;
179+
180+
fn coalesce() -> Self::Future {
181+
OptionCoalesce::Read
182+
}
183+
}

0 commit comments

Comments
 (0)