diff options
Diffstat (limited to 'src/resources.rs')
-rw-r--r-- | src/resources.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/resources.rs b/src/resources.rs index 90b7ce772..36e0d9486 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -20,12 +20,14 @@ use tokio_write; use futures; use futures::future::{Either, FutureResult}; +use futures::Future; use futures::Poll; use hyper; use std; use std::collections::HashMap; use std::io::{Error, Read, Write}; use std::net::{Shutdown, SocketAddr}; +use std::process::ExitStatus; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; use std::sync::Mutex; @@ -33,6 +35,7 @@ use tokio; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::TcpStream; use tokio_io; +use tokio_process; pub type ResourceId = u32; // Sometimes referred to RID. @@ -63,6 +66,10 @@ enum Repr { TcpStream(tokio::net::TcpStream), HttpBody(HttpBody), Repl(Repl), + Child(tokio_process::Child), + ChildStdin(tokio_process::ChildStdin), + ChildStdout(tokio_process::ChildStdout), + ChildStderr(tokio_process::ChildStderr), } pub fn table_entries() -> Vec<(u32, String)> { @@ -94,6 +101,10 @@ fn inspect_repr(repr: &Repr) -> String { Repr::TcpStream(_) => "tcpStream", Repr::HttpBody(_) => "httpBody", Repr::Repl(_) => "repl", + Repr::Child(_) => "child", + Repr::ChildStdin(_) => "childStdin", + Repr::ChildStdout(_) => "childStdout", + Repr::ChildStderr(_) => "childStderr", }; String::from(h_repr) @@ -160,6 +171,8 @@ impl AsyncRead for Resource { Repr::Stdin(ref mut f) => f.poll_read(buf), Repr::TcpStream(ref mut f) => f.poll_read(buf), Repr::HttpBody(ref mut f) => f.poll_read(buf), + Repr::ChildStdout(ref mut f) => f.poll_read(buf), + Repr::ChildStderr(ref mut f) => f.poll_read(buf), _ => panic!("Cannot read"), }, } @@ -187,6 +200,7 @@ impl AsyncWrite for Resource { Repr::Stdout(ref mut f) => f.poll_write(buf), Repr::Stderr(ref mut f) => f.poll_write(buf), Repr::TcpStream(ref mut f) => f.poll_write(buf), + Repr::ChildStdin(ref mut f) => f.poll_write(buf), _ => panic!("Cannot write"), }, } @@ -244,6 +258,80 @@ pub fn add_repl(repl: Repl) -> Resource { Resource { rid } } +pub struct ChildResources { + pub child_rid: ResourceId, + pub stdin_rid: Option<ResourceId>, + pub stdout_rid: Option<ResourceId>, + pub stderr_rid: Option<ResourceId>, +} + +pub fn add_child(mut c: tokio_process::Child) -> ChildResources { + let child_rid = new_rid(); + let mut tg = RESOURCE_TABLE.lock().unwrap(); + + let mut resources = ChildResources { + child_rid, + stdin_rid: None, + stdout_rid: None, + stderr_rid: None, + }; + + if c.stdin().is_some() { + let stdin = c.stdin().take().unwrap(); + let rid = new_rid(); + let r = tg.insert(rid, Repr::ChildStdin(stdin)); + assert!(r.is_none()); + resources.stdin_rid = Some(rid); + } + if c.stdout().is_some() { + let stdout = c.stdout().take().unwrap(); + let rid = new_rid(); + let r = tg.insert(rid, Repr::ChildStdout(stdout)); + assert!(r.is_none()); + resources.stdout_rid = Some(rid); + } + if c.stderr().is_some() { + let stderr = c.stderr().take().unwrap(); + let rid = new_rid(); + let r = tg.insert(rid, Repr::ChildStderr(stderr)); + assert!(r.is_none()); + resources.stderr_rid = Some(rid); + } + + let r = tg.insert(child_rid, Repr::Child(c)); + assert!(r.is_none()); + + return resources; +} + +pub struct ChildStatus { + rid: ResourceId, +} + +// Invert the dumbness that tokio_process causes by making Child itself a future. +impl Future for ChildStatus { + type Item = ExitStatus; + type Error = DenoError; + + fn poll(&mut self) -> Poll<ExitStatus, DenoError> { + let mut table = RESOURCE_TABLE.lock().unwrap(); + let maybe_repr = table.get_mut(&self.rid); + match maybe_repr { + Some(Repr::Child(ref mut child)) => child.poll().map_err(DenoError::from), + _ => Err(bad_resource()), + } + } +} + +pub fn child_status(rid: ResourceId) -> DenoResult<ChildStatus> { + let mut table = RESOURCE_TABLE.lock().unwrap(); + let maybe_repr = table.get_mut(&rid); + match maybe_repr { + Some(Repr::Child(ref mut _child)) => Ok(ChildStatus { rid }), + _ => Err(bad_resource()), + } +} + pub fn readline(rid: ResourceId, prompt: &str) -> DenoResult<String> { let mut table = RESOURCE_TABLE.lock().unwrap(); let maybe_repr = table.get_mut(&rid); |