diff --git a/Cargo.lock b/Cargo.lock index fe843fe46..8329b3924 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4839,12 +4839,12 @@ dependencies = [ "pathdiff", "petgraph", "predicates", - "scarb-proc-macro-server-types", "ra_ap_toolchain", "redb", "reqwest", "scarb-build-metadata", "scarb-metadata 1.13.0", + "scarb-proc-macro-server-types", "scarb-stable-hash 1.0.0", "scarb-test-support", "scarb-ui", diff --git a/scarb/src/ops/proc_macro_server/mod.rs b/scarb/src/ops/proc_macro_server/mod.rs index 3cc30ea1e..6e29f7de0 100644 --- a/scarb/src/ops/proc_macro_server/mod.rs +++ b/scarb/src/ops/proc_macro_server/mod.rs @@ -1,15 +1,64 @@ -use crate::compiler::plugin::proc_macro::ProcMacroHost; -use anyhow::Result; +use std::num::NonZero; +use std::thread::available_parallelism; + +use anyhow::{anyhow, Result}; use connection::Connection; +use crossbeam_channel::{Receiver, Sender}; +use scarb_proc_macro_server_types::jsonrpc::{ResponseError, RpcRequest, RpcResponse}; +use serde_json::Value; + +use crate::compiler::plugin::proc_macro::ProcMacroHost; mod connection; pub fn start_proc_macro_server(proc_macros: ProcMacroHost) -> Result<()> { let connection = Connection::new(); + let available_parallelism = available_parallelism().map(NonZero::get).unwrap_or(4); + + for i in 0..available_parallelism { + let receiver = connection.receiver.clone(); + let sender = connection.sender.clone(); - //TODO + std::thread::Builder::new() + .name(format!("proc-macro-server-worker-thread-{i}")) + .spawn(move || { + handle_requests(receiver, sender); + }) + .expect("failed to spawn thread"); + } connection.join(); Ok(()) } + +fn handle_requests(receiver: Receiver, sender: Sender) { + for request in receiver { + let id = request.id; + let response = route_request(request); + + let response = match response { + Ok(result) => RpcResponse { + id, + result: Some(result), + error: None, + }, + Err(error) => RpcResponse { + id, + result: None, + error: Some(ResponseError { + message: error.to_string(), + }), + }, + }; + + sender.send(response).unwrap(); + } +} + +fn route_request(request: RpcRequest) -> Result { + match request.method.as_str() { + //TODO add method handlers + _ => Err(anyhow!("method not found")), + } +}