Skip to content

Commit

Permalink
create: nacho-js-process crate
Browse files Browse the repository at this point in the history
  • Loading branch information
berzanorg committed Apr 28, 2024
1 parent e38349e commit 2c24249
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ members = [
"schnorr-signature",
"proofs-db",
"macros",
"js-process",
]

[workspace.dependencies]
Expand Down Expand Up @@ -60,6 +61,7 @@ nacho-processes.path = "processes"
nacho-proofpool.path = "proofpool"
nacho-proofs-db.path = "proofs-db"
nacho-prover.path = "prover"
nacho-js-process.path = "js-process"
nacho-rpc-server.path = "rpc-server"
nacho-schnorr-signature.path = "schnorr-signature"
nacho-withdrawals-db.path = "withdrawals-db"
Expand Down
10 changes: 10 additions & 0 deletions js-process/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "nacho-js-process"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio.workspace = true
thiserror.workspace = true
5 changes: 5 additions & 0 deletions js-process/resources/echo.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { stdin, stdout } from "node:process"

stdin.on("data", async (chunk) => {
stdout.write(chunk)
})
12 changes: 12 additions & 0 deletions js-process/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use thiserror::Error;

/// The errors that can occur during spawning and interacting with Node.js processes.
#[derive(Error, Debug)]
pub enum JsProcessError {
#[error("data store disconnected")]
Io(#[from] std::io::Error),
#[error("stdout couldn't be taken from the js process")]
Stdout,
#[error("stdin couldn't be taken from the js process")]
Stdin,
}
96 changes: 96 additions & 0 deletions js-process/src/js_process.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use std::process::Stdio;

use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
process::{ChildStdin, ChildStdout, Command},
};

use crate::error::JsProcessError;

/// Spawns a Node.js process using the given arguments and returns a the standard input and output streams of the process.
///
/// # Examples
///
/// Spawn a process:
///
/// ```rs
/// let (stdin, stdout) = nacho_js_process::spawn(&["echo.js"])?;
/// ```
///
pub fn spawn(
args: &[&str],
) -> Result<(&'static mut ChildStdin, &'static mut ChildStdout), JsProcessError> {
let mut process = Command::new("node")
.args(args)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.kill_on_drop(false)
.spawn()?;

let stdin = process.stdin.take().ok_or(JsProcessError::Stdin)?;
let stdout = process.stdout.take().ok_or(JsProcessError::Stdout)?;

Ok((Box::leak(Box::new(stdin)), Box::leak(Box::new(stdout))))
}

/// Writes the given input to the standard input stream of the process.
///
/// And reads the standart output of the process to the given output.
///
/// # Examples
///
/// Spawn a process:
///
/// ```rs
/// let (stdin, stdout) = nacho_js_process::spawn(&["greeting.js"])?;
/// ```
///
/// Interact with the process:
///
/// ```rs
/// let input = b"Berzan";
/// let mut output = [0u8; 11];
/// nacho_js_process::interact(stdin, stdout, &input, &mut output).await?;
/// assert_eq!(output, b"Hi, Berzan!");
/// ```
///
pub async fn interact(
stdin: &mut ChildStdin,
stdout: &mut ChildStdout,
input: &[u8],
output: &mut [u8],
) -> Result<(), JsProcessError> {
stdin.write_all(input).await?;
stdout.read_exact(output).await?;

Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

#[tokio::test]
pub async fn test_echo_js_process() {
let js_file_path = concat!(env!("CARGO_MANIFEST_DIR"), "/resources/echo.mjs");

let (stdin, stdout) = spawn(&[js_file_path]).unwrap();

// First try:
let input = [111u8; 5];
let mut output = [0u8; 5];

interact(stdin, stdout, &input, &mut output).await.unwrap();

assert_eq!(output, input);

// Second try:
let input = [222u8; 40];
let mut output = [0u8; 40];

interact(stdin, stdout, &input, &mut output).await.unwrap();

assert_eq!(output, input);
}
}
5 changes: 5 additions & 0 deletions js-process/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod error;
mod js_process;

pub use error::JsProcessError;
pub use js_process::{interact, spawn};

0 comments on commit 2c24249

Please sign in to comment.