diff --git a/Cargo.toml b/Cargo.toml index 192c9a2..6466f6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,17 @@ authors = ["MeiK "] edition = "2018" [dependencies] +tonic = "0.3" +prost = "0.6" +tokio = { version = "0.2", features = ["macros", "sync", "stream", "time"] } +futures = { version = "0.3" } +futures-core = "0.3" +futures-util = { version = "0.3", default-features = false } +async-stream = "0.2" +tower = "0.3" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +rand = "0.7" + +[build-dependencies] +tonic-build ={ version = "0.3" } diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..fd7220e --- /dev/null +++ b/build.rs @@ -0,0 +1,4 @@ +fn main() -> Result<(), Box> { + tonic_build::compile_protos("proto/river.proto")?; + Ok(()) +} diff --git a/proto/river.proto b/proto/river.proto new file mode 100644 index 0000000..a8f301b --- /dev/null +++ b/proto/river.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; +package river; + +service River { + rpc Judge(stream JudgeRequest) returns (stream JudgeResponse) {} +} + +message JudgeRequest { + enum Language { + C = 0; + Cpp = 1; + Python = 2; + Rust = 3; + Node = 4; + TypeScript = 5; + Go = 6; + } + Language language = 1; + + string code = 2; + + enum JudgeType { + Standard = 0; + // Special = 1; + } + JudgeType judge_type = 3; + + string in_data = 4; + string out_data = 5; + + int32 time_limit = 6; + int32 memory_limit = 7; +} + +message JudgeResponse { + int32 time_used = 1; + int32 memory_used = 2; + enum JudgeResult { + Accepted = 0; + WrongAnswer = 1; + TimeLimitExceeded = 2; + MemoryLimitExceeded = 3; + RuntimeError = 4; + OutputLimitExceeded = 5; + CompileError = 6; + PresentationError = 7; + SystemError = 8; + } + JudgeResult result = 3; + int32 errno = 4; + int32 exit_code = 5; + string stdout = 6; + string stderr = 7; +} diff --git a/src/main.rs b/src/main.rs index 47ad8c6..418bb40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,56 @@ -fn main() { - println!("Hello World!"); +use futures_core::Stream; +use river::river_server::{River, RiverServer}; +use river::{JudgeRequest, JudgeResponse}; +use std::pin::Pin; +use std::sync::Arc; +use tokio::sync::mpsc; +use tonic::{transport::Server, Request, Response, Status}; + +pub mod river { + tonic::include_proto!("river"); // The string specified here must match the proto package name +} + +#[derive(Debug, Default)] +pub struct RiverService {} + +#[tonic::async_trait] +impl River for RiverService { + type JudgeStream = + Pin> + Send + Sync + 'static>>; + + async fn judge( + &self, + request: Request>, + ) -> Result, Status> { + let mut stream = request.into_inner(); + + let output = async_stream::try_stream! { + // while let Some(note) = stream.next().await { + yield river::JudgeResponse { + time_used: 1, + memory_used: 2, + result: 0, + errno: 0, + exit_code: 0, + stdout: "stdout".into(), + stderr: "stderr".into(), + }; + // } + }; + + Ok(Response::new(Box::pin(output) as Self::JudgeStream)) + } +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let addr = "[::1]:50051".parse()?; + let greeter = RiverService::default(); + + Server::builder() + .add_service(RiverServer::new(greeter)) + .serve(addr) + .await?; + + Ok(()) }