Skip to content

Commit

Permalink
feat: 🚧 try adding AsyncComparer to replace async-trait
Browse files Browse the repository at this point in the history
  • Loading branch information
Jisu-Woniu committed Mar 2, 2024
1 parent 9c6992f commit 781f0d1
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions crates/rsjudge-judger/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ rust-version.workspace = true

[dependencies]
async-trait = "0.1.77"
tokio = { version = "1.36.0", features = ["io-util", "fs"] }
pin-project = "1.1.4"
tokio = { version = "1.36.0", features = ["io-util", "fs", "macros"] }
tokio-stream = { version = "0.1.14", features = ["io-util", "tokio-util"] }

[dev-dependencies]
temp-dir = "0.1.12"
tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] }
tokio = { version = "1.36.0", features = ["rt-multi-thread"] }
73 changes: 73 additions & 0 deletions crates/rsjudge-judger/src/comparer/compare.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::{
future::Future,
io,
marker::PhantomPinned,
pin::Pin,
task::{ready, Context, Poll},
};

use pin_project::pin_project;
use tokio::io::AsyncRead;

use super::AsyncComparer;
use crate::CompareResult;

#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[pin_project]
pub struct Compare<'a, C: ?Sized, Out, Ans> {
comparer: &'a mut C,
out: Out,
ans: Ans,

// Make this future `!Unpin` for compatibility with async trait methods.
#[pin]
_pin: PhantomPinned,
}

pub(super) fn compare<'a, C, Out, Ans>(
comparer: &'a mut C,
out: Out,
ans: Ans,
) -> Compare<'a, C, Out, Ans>
where
C: AsyncComparer + Unpin + ?Sized,
Out: AsyncRead + Unpin,
Ans: AsyncRead + Unpin,
{
Compare {
comparer,
out,
ans,
_pin: PhantomPinned,
}
}

fn compare_internal<C, Out, Ans>(
mut comparer: Pin<&mut C>,
cx: &mut Context,
out: Out,
ans: Ans,
) -> Poll<io::Result<CompareResult>>
where
C: AsyncComparer + Unpin + ?Sized,
Out: AsyncRead + Unpin,
Ans: AsyncRead + Unpin,
{
Poll::Ready(ready!(comparer.as_mut().poll_compare(cx, out, ans)))
}

impl<'c, C, Out, Ans> Future for Compare<'c, C, Out, Ans>
where
C: AsyncComparer + Unpin + ?Sized,
Out: AsyncRead + Unpin,
Ans: AsyncRead + Unpin,
{
type Output = io::Result<CompareResult>;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = self.project();

compare_internal(Pin::new(*me.comparer), cx, me.out, me.ans)
}
}
47 changes: 47 additions & 0 deletions crates/rsjudge-judger/src/comparer/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
pub mod compare;
use std::{
pin::Pin,
task::{Context, Poll},
};

use async_trait::async_trait;
use tokio::io::{self, AsyncRead};

use self::compare::{compare, Compare};

#[derive(Debug, PartialEq)]
pub enum CompareResult {
Accepted,
WrongAnswer,
PresentationError,
}

// TODO: Migrate to AsyncComparer trait
#[async_trait]
pub trait Comparer {
async fn compare<Out, Ans>(&self, out: Out, ans: Ans) -> io::Result<CompareResult>
where
Out: AsyncRead + Send + Unpin,
Ans: AsyncRead + Send + Unpin;
}

pub trait AsyncComparer {
fn poll_compare<Out, Ans>(
self: Pin<&mut Self>,
cx: &mut Context,
out: Out,
ans: Ans,
) -> Poll<io::Result<CompareResult>>
where
Out: AsyncRead + Unpin,
Ans: AsyncRead + Unpin;

fn compare<'a, Out, Ans>(&'a mut self, out: Out, ans: Ans) -> Compare<'a, Self, Out, Ans>
where
Self: Unpin,
Out: AsyncRead + Send + Unpin,
Ans: AsyncRead + Send + Unpin,
{
compare(self, out, ans)
}
}
1 change: 0 additions & 1 deletion crates/rsjudge-judger/src/default_comparer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ impl Comparer for DefaultComparer {
let out = BufReader::new(out);
let ans = BufReader::new(ans);

// LinesStream::new(out.lines())
let mut out_lines = LinesStream::new(out.lines());
let mut ans_lines = LinesStream::new(ans.lines());

Expand Down
19 changes: 2 additions & 17 deletions crates/rsjudge-judger/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,4 @@
use async_trait::async_trait;
use tokio::io::{self, AsyncRead};
pub mod comparer;
pub mod default_comparer;

#[derive(Debug, PartialEq)]
pub enum CompareResult {
Accepted,
WrongAnswer,
PresentationError,
}

// TODO: Add `Compare` type and mannually implement `Future` trait for it.
#[async_trait]
pub trait Comparer {
async fn compare<Out, Ans>(&self, out: Out, ans: Ans) -> io::Result<CompareResult>
where
Out: AsyncRead + Send + Unpin,
Ans: AsyncRead + Send + Unpin;
}
pub use comparer::{CompareResult, Comparer};

0 comments on commit 781f0d1

Please sign in to comment.