1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-12 00:54:02 -05:00

refactor: remove cli::resources::Resource (#3285)

This commit is contained in:
Bartek Iwańczuk 2019-11-07 17:11:15 +01:00 committed by Ry Dahl
parent 415d4c2e52
commit 25c276055b
11 changed files with 219 additions and 301 deletions

View file

@ -50,9 +50,7 @@ pub mod source_maps;
mod startup_data; mod startup_data;
pub mod state; pub mod state;
pub mod test_util; pub mod test_util;
mod tokio_read;
mod tokio_util; mod tokio_util;
mod tokio_write;
pub mod version; pub mod version;
pub mod worker; pub mod worker;

View file

@ -62,10 +62,10 @@ pub fn op_fetch(
} }
let body = res.into_body(); let body = res.into_body();
let body_resource = resources::add_reqwest_body(body); let rid = resources::add_reqwest_body(body);
let json_res = json!({ let json_res = json!({
"bodyRid": body_resource.rid, "bodyRid": rid,
"status": status.as_u16(), "status": status.as_u16(),
"statusText": status.canonical_reason().unwrap_or(""), "statusText": status.canonical_reason().unwrap_or(""),
"headers": res_headers "headers": res_headers

View file

@ -1,14 +1,19 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use super::dispatch_json::{Deserialize, JsonOp, Value}; use super::dispatch_json::{Deserialize, JsonOp, Value};
use crate::deno_error::bad_resource; use crate::deno_error::bad_resource;
use crate::deno_error::DenoError;
use crate::deno_error::ErrorKind;
use crate::fs as deno_fs; use crate::fs as deno_fs;
use crate::ops::json_op; use crate::ops::json_op;
use crate::resources; use crate::resources;
use crate::resources::CliResource;
use crate::state::ThreadSafeState; use crate::state::ThreadSafeState;
use deno::*; use deno::*;
use futures::Future; use futures::Future;
use futures::Poll;
use std; use std;
use std::convert::From; use std::convert::From;
use std::io::SeekFrom;
use tokio; use tokio;
pub fn init(i: &mut Isolate, s: &ThreadSafeState) { pub fn init(i: &mut Isolate, s: &ThreadSafeState) {
@ -86,8 +91,8 @@ fn op_open(
let is_sync = args.promise_id.is_none(); let is_sync = args.promise_id.is_none();
let op = open_options.open(filename).map_err(ErrBox::from).and_then( let op = open_options.open(filename).map_err(ErrBox::from).and_then(
move |fs_file| { move |fs_file| {
let resource = resources::add_fs_file(fs_file); let rid = resources::add_fs_file(fs_file);
futures::future::ok(json!(resource.rid)) futures::future::ok(json!(rid))
}, },
); );
@ -116,6 +121,31 @@ fn op_close(
Ok(JsonOp::Sync(json!({}))) Ok(JsonOp::Sync(json!({})))
} }
#[derive(Debug)]
pub struct SeekFuture {
seek_from: SeekFrom,
rid: ResourceId,
}
impl Future for SeekFuture {
type Item = u64;
type Error = ErrBox;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut table = resources::lock_resource_table();
let resource = table
.get_mut::<CliResource>(self.rid)
.ok_or_else(bad_resource)?;
let tokio_file = match resource {
CliResource::FsFile(ref mut file) => file,
_ => return Err(bad_resource()),
};
tokio_file.poll_seek(self.seek_from).map_err(ErrBox::from)
}
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct SeekArgs { struct SeekArgs {
@ -131,10 +161,25 @@ fn op_seek(
_zero_copy: Option<PinnedBuf>, _zero_copy: Option<PinnedBuf>,
) -> Result<JsonOp, ErrBox> { ) -> Result<JsonOp, ErrBox> {
let args: SeekArgs = serde_json::from_value(args)?; let args: SeekArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
let offset = args.offset;
let whence = args.whence as u32;
// Translate seek mode to Rust repr.
let seek_from = match whence {
0 => SeekFrom::Start(offset as u64),
1 => SeekFrom::Current(i64::from(offset)),
2 => SeekFrom::End(i64::from(offset)),
_ => {
return Err(ErrBox::from(DenoError::new(
ErrorKind::InvalidSeekMode,
format!("Invalid seek mode: {}", whence),
)));
}
};
let resource = resources::lookup(args.rid as u32)?; let fut = SeekFuture { seek_from, rid };
let op = resources::seek(resource, args.offset, args.whence as u32)
.and_then(move |_| futures::future::ok(json!({}))); let op = fut.and_then(move |_| futures::future::ok(json!({})));
if args.promise_id.is_none() { if args.promise_id.is_none() {
let buf = op.wait()?; let buf = op.wait()?;
Ok(JsonOp::Sync(buf)) Ok(JsonOp::Sync(buf))

View file

@ -1,18 +1,76 @@
use super::dispatch_minimal::MinimalOp; use super::dispatch_minimal::MinimalOp;
use crate::deno_error; use crate::deno_error;
use crate::deno_error::bad_resource;
use crate::ops::minimal_op; use crate::ops::minimal_op;
use crate::resources; use crate::resources;
use crate::resources::CliResource;
use crate::resources::DenoAsyncRead;
use crate::resources::DenoAsyncWrite;
use crate::state::ThreadSafeState; use crate::state::ThreadSafeState;
use crate::tokio_read;
use crate::tokio_write;
use deno::*; use deno::*;
use futures::Future; use futures::Future;
use futures::Poll;
pub fn init(i: &mut Isolate, s: &ThreadSafeState) { pub fn init(i: &mut Isolate, s: &ThreadSafeState) {
i.register_op("read", s.core_op(minimal_op(op_read))); i.register_op("read", s.core_op(minimal_op(op_read)));
i.register_op("write", s.core_op(minimal_op(op_write))); i.register_op("write", s.core_op(minimal_op(op_write)));
} }
#[derive(Debug, PartialEq)]
enum IoState {
Pending,
Done,
}
/// Tries to read some bytes directly into the given `buf` in asynchronous
/// manner, returning a future type.
///
/// The returned future will resolve to both the I/O stream and the buffer
/// as well as the number of bytes read once the read operation is completed.
pub fn read<T>(rid: ResourceId, buf: T) -> Read<T>
where
T: AsMut<[u8]>,
{
Read {
rid,
buf,
state: IoState::Pending,
}
}
/// A future which can be used to easily read available number of bytes to fill
/// a buffer.
///
/// Created by the [`read`] function.
#[derive(Debug)]
pub struct Read<T> {
rid: ResourceId,
buf: T,
state: IoState,
}
impl<T> Future for Read<T>
where
T: AsMut<[u8]>,
{
type Item = usize;
type Error = ErrBox;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.state == IoState::Done {
panic!("poll a Read after it's done");
}
let mut table = resources::lock_resource_table();
let resource = table
.get_mut::<CliResource>(self.rid)
.ok_or_else(bad_resource)?;
let nread = try_ready!(resource.poll_read(&mut self.buf.as_mut()[..]));
self.state = IoState::Done;
Ok(nread.into())
}
}
pub fn op_read(rid: i32, zero_copy: Option<PinnedBuf>) -> Box<MinimalOp> { pub fn op_read(rid: i32, zero_copy: Option<PinnedBuf>) -> Box<MinimalOp> {
debug!("read rid={}", rid); debug!("read rid={}", rid);
let zero_copy = match zero_copy { let zero_copy = match zero_copy {
@ -22,13 +80,58 @@ pub fn op_read(rid: i32, zero_copy: Option<PinnedBuf>) -> Box<MinimalOp> {
Some(buf) => buf, Some(buf) => buf,
}; };
match resources::lookup(rid as u32) { let fut = read(rid as u32, zero_copy)
Err(e) => Box::new(futures::future::err(e)),
Ok(resource) => Box::new(
tokio_read::read(resource, zero_copy)
.map_err(ErrBox::from) .map_err(ErrBox::from)
.and_then(move |(_resource, _buf, nread)| Ok(nread as i32)), .and_then(move |nread| Ok(nread as i32));
),
Box::new(fut)
}
/// A future used to write some data to a stream.
#[derive(Debug)]
pub struct Write<T> {
rid: ResourceId,
buf: T,
state: IoState,
}
/// Creates a future that will write some of the buffer `buf` to
/// the stream resource with `rid`.
///
/// Any error which happens during writing will cause both the stream and the
/// buffer to get destroyed.
pub fn write<T>(rid: ResourceId, buf: T) -> Write<T>
where
T: AsRef<[u8]>,
{
Write {
rid,
buf,
state: IoState::Pending,
}
}
/// This is almost the same implementation as in tokio, difference is
/// that error type is `ErrBox` instead of `std::io::Error`.
impl<T> Future for Write<T>
where
T: AsRef<[u8]>,
{
type Item = usize;
type Error = ErrBox;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if self.state == IoState::Done {
panic!("poll a Read after it's done");
}
let mut table = resources::lock_resource_table();
let resource = table
.get_mut::<CliResource>(self.rid)
.ok_or_else(bad_resource)?;
let nwritten = try_ready!(resource.poll_write(self.buf.as_ref()));
self.state = IoState::Done;
Ok(nwritten.into())
} }
} }
@ -41,12 +144,9 @@ pub fn op_write(rid: i32, zero_copy: Option<PinnedBuf>) -> Box<MinimalOp> {
Some(buf) => buf, Some(buf) => buf,
}; };
match resources::lookup(rid as u32) { let fut = write(rid as u32, zero_copy)
Err(e) => Box::new(futures::future::err(e)),
Ok(resource) => Box::new(
tokio_write::write(resource, zero_copy)
.map_err(ErrBox::from) .map_err(ErrBox::from)
.and_then(move |(_resource, _buf, nwritten)| Ok(nwritten as i32)), .and_then(move |nwritten| Ok(nwritten as i32));
),
} Box::new(fut)
} }

View file

@ -4,7 +4,7 @@ use crate::deno_error::bad_resource;
use crate::ops::json_op; use crate::ops::json_op;
use crate::resolve_addr::resolve_addr; use crate::resolve_addr::resolve_addr;
use crate::resources; use crate::resources;
use crate::resources::CoreResource; use crate::resources::CliResource;
use crate::resources::Resource; use crate::resources::Resource;
use crate::state::ThreadSafeState; use crate::state::ThreadSafeState;
use deno::*; use deno::*;
@ -132,13 +132,13 @@ fn op_accept(
.and_then(move |(tcp_stream, _socket_addr)| { .and_then(move |(tcp_stream, _socket_addr)| {
let local_addr = tcp_stream.local_addr()?; let local_addr = tcp_stream.local_addr()?;
let remote_addr = tcp_stream.peer_addr()?; let remote_addr = tcp_stream.peer_addr()?;
let tcp_stream_resource = resources::add_tcp_stream(tcp_stream); let rid = resources::add_tcp_stream(tcp_stream);
Ok((tcp_stream_resource, local_addr, remote_addr)) Ok((rid, local_addr, remote_addr))
}) })
.map_err(ErrBox::from) .map_err(ErrBox::from)
.and_then(move |(tcp_stream_resource, local_addr, remote_addr)| { .and_then(move |(rid, local_addr, remote_addr)| {
futures::future::ok(json!({ futures::future::ok(json!({
"rid": tcp_stream_resource.rid, "rid": rid,
"localAddr": local_addr.to_string(), "localAddr": local_addr.to_string(),
"remoteAddr": remote_addr.to_string(), "remoteAddr": remote_addr.to_string(),
})) }))
@ -170,13 +170,13 @@ fn op_dial(
.and_then(move |tcp_stream| { .and_then(move |tcp_stream| {
let local_addr = tcp_stream.local_addr()?; let local_addr = tcp_stream.local_addr()?;
let remote_addr = tcp_stream.peer_addr()?; let remote_addr = tcp_stream.peer_addr()?;
let tcp_stream_resource = resources::add_tcp_stream(tcp_stream); let rid = resources::add_tcp_stream(tcp_stream);
Ok((tcp_stream_resource, local_addr, remote_addr)) Ok((rid, local_addr, remote_addr))
}) })
.map_err(ErrBox::from) .map_err(ErrBox::from)
.and_then(move |(tcp_stream_resource, local_addr, remote_addr)| { .and_then(move |(rid, local_addr, remote_addr)| {
futures::future::ok(json!({ futures::future::ok(json!({
"rid": tcp_stream_resource.rid, "rid": rid,
"localAddr": local_addr.to_string(), "localAddr": local_addr.to_string(),
"remoteAddr": remote_addr.to_string(), "remoteAddr": remote_addr.to_string(),
})) }))
@ -201,7 +201,6 @@ fn op_shutdown(
let rid = args.rid as u32; let rid = args.rid as u32;
let how = args.how; let how = args.how;
let mut resource = resources::lookup(rid)?;
let shutdown_mode = match how { let shutdown_mode = match how {
0 => Shutdown::Read, 0 => Shutdown::Read,
@ -209,8 +208,15 @@ fn op_shutdown(
_ => unimplemented!(), _ => unimplemented!(),
}; };
// Use UFCS for disambiguation let mut table = resources::lock_resource_table();
Resource::shutdown(&mut resource, shutdown_mode)?; let resource = table.get_mut::<CliResource>(rid).ok_or_else(bad_resource)?;
match resource {
CliResource::TcpStream(ref mut stream) => {
TcpStream::shutdown(stream, shutdown_mode).map_err(ErrBox::from)?;
}
_ => return Err(bad_resource()),
}
Ok(JsonOp::Sync(json!({}))) Ok(JsonOp::Sync(json!({})))
} }
@ -228,7 +234,7 @@ struct TcpListenerResource {
local_addr: SocketAddr, local_addr: SocketAddr,
} }
impl CoreResource for TcpListenerResource {} impl Resource for TcpListenerResource {}
impl Drop for TcpListenerResource { impl Drop for TcpListenerResource {
fn drop(&mut self) { fn drop(&mut self) {

View file

@ -5,7 +5,7 @@ use crate::ops::json_op;
use crate::repl; use crate::repl;
use crate::repl::Repl; use crate::repl::Repl;
use crate::resources; use crate::resources;
use crate::resources::CoreResource; use crate::resources::Resource;
use crate::state::ThreadSafeState; use crate::state::ThreadSafeState;
use deno::*; use deno::*;
use std::sync::Arc; use std::sync::Arc;
@ -24,7 +24,7 @@ pub fn init(i: &mut Isolate, s: &ThreadSafeState) {
struct ReplResource(Arc<Mutex<Repl>>); struct ReplResource(Arc<Mutex<Repl>>);
impl CoreResource for ReplResource {} impl Resource for ReplResource {}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]

View file

@ -6,7 +6,7 @@ use crate::deno_error::ErrorKind;
use crate::ops::json_op; use crate::ops::json_op;
use crate::resolve_addr::resolve_addr; use crate::resolve_addr::resolve_addr;
use crate::resources; use crate::resources;
use crate::resources::CoreResource; use crate::resources::Resource;
use crate::state::ThreadSafeState; use crate::state::ThreadSafeState;
use deno::*; use deno::*;
use futures::Async; use futures::Async;
@ -99,9 +99,9 @@ pub fn op_dial_tls(
.connect(dnsname, tcp_stream) .connect(dnsname, tcp_stream)
.map_err(ErrBox::from) .map_err(ErrBox::from)
.and_then(move |tls_stream| { .and_then(move |tls_stream| {
let tls_stream_resource = resources::add_tls_stream(tls_stream); let rid = resources::add_tls_stream(tls_stream);
futures::future::ok(json!({ futures::future::ok(json!({
"rid": tls_stream_resource.rid, "rid": rid,
"localAddr": local_addr.to_string(), "localAddr": local_addr.to_string(),
"remoteAddr": remote_addr.to_string(), "remoteAddr": remote_addr.to_string(),
})) }))
@ -179,7 +179,7 @@ pub struct TlsListenerResource {
local_addr: SocketAddr, local_addr: SocketAddr,
} }
impl CoreResource for TlsListenerResource {} impl Resource for TlsListenerResource {}
impl Drop for TlsListenerResource { impl Drop for TlsListenerResource {
fn drop(&mut self) { fn drop(&mut self) {
@ -389,14 +389,13 @@ fn op_accept_tls(
.accept(tcp_stream) .accept(tcp_stream)
.map_err(ErrBox::from) .map_err(ErrBox::from)
.and_then(move |tls_stream| { .and_then(move |tls_stream| {
let tls_stream_resource = let rid = resources::add_server_tls_stream(tls_stream);
resources::add_server_tls_stream(tls_stream); Ok((rid, local_addr, remote_addr))
Ok((tls_stream_resource, local_addr, remote_addr))
}) })
}) })
.and_then(move |(tls_stream_resource, local_addr, remote_addr)| { .and_then(move |(rid, local_addr, remote_addr)| {
futures::future::ok(json!({ futures::future::ok(json!({
"rid": tls_stream_resource.rid, "rid": rid,
"localAddr": local_addr.to_string(), "localAddr": local_addr.to_string(),
"remoteAddr": remote_addr.to_string(), "remoteAddr": remote_addr.to_string(),
})) }))

View file

@ -8,11 +8,10 @@
// descriptors". This module implements a global resource table. Ops (AKA // descriptors". This module implements a global resource table. Ops (AKA
// handlers) look up resources by their integer id here. // handlers) look up resources by their integer id here.
use crate::deno_error;
use crate::deno_error::bad_resource; use crate::deno_error::bad_resource;
use crate::http_body::HttpBody; use crate::http_body::HttpBody;
use deno::ErrBox; use deno::ErrBox;
pub use deno::Resource as CoreResource; pub use deno::Resource;
pub use deno::ResourceId; pub use deno::ResourceId;
use deno::ResourceTable; use deno::ResourceTable;
@ -21,8 +20,6 @@ use futures::Future;
use futures::Poll; use futures::Poll;
use reqwest::r#async::Decoder as ReqwestDecoder; use reqwest::r#async::Decoder as ReqwestDecoder;
use std; use std;
use std::io::{Read, Seek, SeekFrom, Write};
use std::net::Shutdown;
use std::process::ExitStatus; use std::process::ExitStatus;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::MutexGuard; use std::sync::MutexGuard;
@ -66,7 +63,7 @@ lazy_static! {
} }
// TODO: move listeners out of this enum and rename to `StreamResource` // TODO: move listeners out of this enum and rename to `StreamResource`
enum CliResource { pub enum CliResource {
Stdin(tokio::io::Stdin), Stdin(tokio::io::Stdin),
Stdout(tokio::fs::File), Stdout(tokio::fs::File),
Stderr(tokio::io::Stderr), Stderr(tokio::io::Stderr),
@ -84,60 +81,21 @@ enum CliResource {
ChildStderr(tokio_process::ChildStderr), ChildStderr(tokio_process::ChildStderr),
} }
impl CoreResource for CliResource {} impl Resource for CliResource {}
pub fn lock_resource_table<'a>() -> MutexGuard<'a, ResourceTable> { pub fn lock_resource_table<'a>() -> MutexGuard<'a, ResourceTable> {
RESOURCE_TABLE.lock().unwrap() RESOURCE_TABLE.lock().unwrap()
} }
// Abstract async file interface.
// Ideally in unix, if Resource represents an OS rid, it will be the same.
#[derive(Clone, Debug)]
pub struct Resource {
pub rid: ResourceId,
}
impl Resource {
// close(2) is done by dropping the value. Therefore we just need to remove
// the resource from the RESOURCE_TABLE.
pub fn close(&self) {
let mut table = lock_resource_table();
table.close(self.rid).unwrap();
}
pub fn shutdown(&mut self, how: Shutdown) -> Result<(), ErrBox> {
let mut table = lock_resource_table();
let repr = table
.get_mut::<CliResource>(self.rid)
.ok_or_else(bad_resource)?;
match repr {
CliResource::TcpStream(ref mut f) => {
TcpStream::shutdown(f, how).map_err(ErrBox::from)
}
_ => Err(bad_resource()),
}
}
}
impl Read for Resource {
fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
unimplemented!();
}
}
/// `DenoAsyncRead` is the same as the `tokio_io::AsyncRead` trait /// `DenoAsyncRead` is the same as the `tokio_io::AsyncRead` trait
/// but uses an `ErrBox` error instead of `std::io:Error` /// but uses an `ErrBox` error instead of `std::io:Error`
pub trait DenoAsyncRead { pub trait DenoAsyncRead {
fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, ErrBox>; fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, ErrBox>;
} }
impl DenoAsyncRead for Resource { impl DenoAsyncRead for CliResource {
fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, ErrBox> { fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, ErrBox> {
let mut table = lock_resource_table(); let r = match self {
let repr = table.get_mut(self.rid).ok_or_else(bad_resource)?;
let r = match repr {
CliResource::FsFile(ref mut f) => f.poll_read(buf), CliResource::FsFile(ref mut f) => f.poll_read(buf),
CliResource::Stdin(ref mut f) => f.poll_read(buf), CliResource::Stdin(ref mut f) => f.poll_read(buf),
CliResource::TcpStream(ref mut f) => f.poll_read(buf), CliResource::TcpStream(ref mut f) => f.poll_read(buf),
@ -155,16 +113,6 @@ impl DenoAsyncRead for Resource {
} }
} }
impl Write for Resource {
fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
unimplemented!()
}
fn flush(&mut self) -> std::io::Result<()> {
unimplemented!()
}
}
/// `DenoAsyncWrite` is the same as the `tokio_io::AsyncWrite` trait /// `DenoAsyncWrite` is the same as the `tokio_io::AsyncWrite` trait
/// but uses an `ErrBox` error instead of `std::io:Error` /// but uses an `ErrBox` error instead of `std::io:Error`
pub trait DenoAsyncWrite { pub trait DenoAsyncWrite {
@ -173,14 +121,9 @@ pub trait DenoAsyncWrite {
fn shutdown(&mut self) -> Poll<(), ErrBox>; fn shutdown(&mut self) -> Poll<(), ErrBox>;
} }
impl DenoAsyncWrite for Resource { impl DenoAsyncWrite for CliResource {
fn poll_write(&mut self, buf: &[u8]) -> Poll<usize, ErrBox> { fn poll_write(&mut self, buf: &[u8]) -> Poll<usize, ErrBox> {
let mut table = lock_resource_table(); let r = match self {
let repr = table
.get_mut::<CliResource>(self.rid)
.ok_or_else(bad_resource)?;
let r = match repr {
CliResource::FsFile(ref mut f) => f.poll_write(buf), CliResource::FsFile(ref mut f) => f.poll_write(buf),
CliResource::Stdout(ref mut f) => f.poll_write(buf), CliResource::Stdout(ref mut f) => f.poll_write(buf),
CliResource::Stderr(ref mut f) => f.poll_write(buf), CliResource::Stderr(ref mut f) => f.poll_write(buf),
@ -201,41 +144,36 @@ impl DenoAsyncWrite for Resource {
} }
} }
pub fn add_fs_file(fs_file: tokio::fs::File) -> Resource { pub fn add_fs_file(fs_file: tokio::fs::File) -> ResourceId {
let mut table = lock_resource_table(); let mut table = lock_resource_table();
let rid = table.add("fsFile", Box::new(CliResource::FsFile(fs_file))); table.add("fsFile", Box::new(CliResource::FsFile(fs_file)))
Resource { rid }
} }
pub fn add_tcp_stream(stream: tokio::net::TcpStream) -> Resource { pub fn add_tcp_stream(stream: tokio::net::TcpStream) -> ResourceId {
let mut table = lock_resource_table(); let mut table = lock_resource_table();
let rid = table.add("tcpStream", Box::new(CliResource::TcpStream(stream))); table.add("tcpStream", Box::new(CliResource::TcpStream(stream)))
Resource { rid }
} }
pub fn add_tls_stream(stream: ClientTlsStream<TcpStream>) -> Resource { pub fn add_tls_stream(stream: ClientTlsStream<TcpStream>) -> ResourceId {
let mut table = lock_resource_table(); let mut table = lock_resource_table();
let rid = table.add( table.add(
"clientTlsStream", "clientTlsStream",
Box::new(CliResource::ClientTlsStream(Box::new(stream))), Box::new(CliResource::ClientTlsStream(Box::new(stream))),
); )
Resource { rid }
} }
pub fn add_server_tls_stream(stream: ServerTlsStream<TcpStream>) -> Resource { pub fn add_server_tls_stream(stream: ServerTlsStream<TcpStream>) -> ResourceId {
let mut table = lock_resource_table(); let mut table = lock_resource_table();
let rid = table.add( table.add(
"serverTlsStream", "serverTlsStream",
Box::new(CliResource::ServerTlsStream(Box::new(stream))), Box::new(CliResource::ServerTlsStream(Box::new(stream))),
); )
Resource { rid }
} }
pub fn add_reqwest_body(body: ReqwestDecoder) -> Resource { pub fn add_reqwest_body(body: ReqwestDecoder) -> ResourceId {
let body = HttpBody::from(body); let body = HttpBody::from(body);
let mut table = lock_resource_table(); let mut table = lock_resource_table();
let rid = table.add("httpBody", Box::new(CliResource::HttpBody(body))); table.add("httpBody", Box::new(CliResource::HttpBody(body)))
Resource { rid }
} }
pub struct ChildResources { pub struct ChildResources {
@ -347,40 +285,3 @@ pub fn get_file(rid: ResourceId) -> Result<std::fs::File, ErrBox> {
_ => Err(bad_resource()), _ => Err(bad_resource()),
} }
} }
pub fn lookup(rid: ResourceId) -> Result<Resource, ErrBox> {
debug!("resource lookup {}", rid);
let table = lock_resource_table();
let _ = table.get::<CliResource>(rid).ok_or_else(bad_resource)?;
Ok(Resource { rid })
}
pub fn seek(
resource: Resource,
offset: i32,
whence: u32,
) -> Box<dyn Future<Item = (), Error = ErrBox> + Send> {
// Translate seek mode to Rust repr.
let seek_from = match whence {
0 => SeekFrom::Start(offset as u64),
1 => SeekFrom::Current(i64::from(offset)),
2 => SeekFrom::End(i64::from(offset)),
_ => {
return Box::new(futures::future::err(
deno_error::DenoError::new(
deno_error::ErrorKind::InvalidSeekMode,
format!("Invalid seek mode: {}", whence),
)
.into(),
));
}
};
match get_file(resource.rid) {
Ok(mut file) => Box::new(futures::future::lazy(move || {
let result = file.seek(seek_from).map(|_| {}).map_err(ErrBox::from);
futures::future::result(result)
})),
Err(err) => Box::new(futures::future::err(err)),
}
}

View file

@ -1,64 +0,0 @@
// Copyright (c) 2019 Tokio Contributors. All rights reserved. MIT license.
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// Forked from: https://github.com/tokio-rs/tokio/blob/9b3f8564af4bb1aee07fab3c401eb412ca5eeac5/tokio-io/src/io/read.rs
use crate::resources::DenoAsyncRead;
use deno::ErrBox;
use futures::{Future, Poll};
use std::mem;
/// This is almost the same implementation as in tokio, the only difference is
/// that error type is `ErrBox` instead of `std::io::Error`.
#[derive(Debug)]
enum State<R, T> {
Pending { rd: R, buf: T },
Empty,
}
/// Tries to read some bytes directly into the given `buf` in asynchronous
/// manner, returning a future type.
///
/// The returned future will resolve to both the I/O stream and the buffer
/// as well as the number of bytes read once the read operation is completed.
pub fn read<R, T>(rd: R, buf: T) -> Read<R, T>
where
R: DenoAsyncRead,
T: AsMut<[u8]>,
{
Read {
state: State::Pending { rd, buf },
}
}
/// A future which can be used to easily read available number of bytes to fill
/// a buffer.
///
/// Created by the [`read`] function.
#[derive(Debug)]
pub struct Read<R, T> {
state: State<R, T>,
}
impl<R, T> Future for Read<R, T>
where
R: DenoAsyncRead,
T: AsMut<[u8]>,
{
type Item = (R, T, usize);
type Error = ErrBox;
fn poll(&mut self) -> Poll<(R, T, usize), ErrBox> {
let nread = match self.state {
State::Pending {
ref mut rd,
ref mut buf,
} => try_ready!(rd.poll_read(&mut buf.as_mut()[..])),
State::Empty => panic!("poll a Read after it's done"),
};
match mem::replace(&mut self.state, State::Empty) {
State::Pending { rd, buf } => Ok((rd, buf, nread).into()),
State::Empty => panic!("invalid internal state"),
}
}
}

View file

@ -1,62 +0,0 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::resources::DenoAsyncWrite;
use deno::ErrBox;
use futures::{Future, Poll};
use std::mem;
/// A future used to write some data to a stream.
///
/// This is created by the [`write`] top-level method.
///
/// [`write`]: fn.write.html
#[derive(Debug)]
pub struct Write<A, T> {
state: State<A, T>,
}
#[derive(Debug)]
enum State<A, T> {
Pending { a: A, buf: T },
Empty,
}
/// Creates a future that will write some of the buffer `buf` to
/// the stream `a` provided.
///
/// Any error which happens during writing will cause both the stream and the
/// buffer to get destroyed.
pub fn write<A, T>(a: A, buf: T) -> Write<A, T>
where
A: DenoAsyncWrite,
T: AsRef<[u8]>,
{
Write {
state: State::Pending { a, buf },
}
}
/// This is almost the same implementation as in tokio, difference is
/// that error type is `ErrBox` instead of `std::io::Error`.
impl<A, T> Future for Write<A, T>
where
A: DenoAsyncWrite,
T: AsRef<[u8]>,
{
type Item = (A, T, usize);
type Error = ErrBox;
fn poll(&mut self) -> Poll<(A, T, usize), ErrBox> {
let nwritten = match self.state {
State::Pending {
ref mut a,
ref mut buf,
} => try_ready!(a.poll_write(buf.as_ref())),
State::Empty => panic!("poll a Read after it's done"),
};
match mem::replace(&mut self.state, State::Empty) {
State::Pending { a, buf } => Ok((a, buf, nwritten).into()),
State::Empty => panic!("invalid internal state"),
}
}
}

View file

@ -3,7 +3,7 @@ use crate::deno_error::bad_resource;
use crate::fmt_errors::JSError; use crate::fmt_errors::JSError;
use crate::ops; use crate::ops;
use crate::resources; use crate::resources;
use crate::resources::CoreResource; use crate::resources::Resource;
use crate::resources::ResourceId; use crate::resources::ResourceId;
use crate::state::ThreadSafeState; use crate::state::ThreadSafeState;
use deno; use deno;
@ -31,7 +31,7 @@ pub struct WorkerChannels {
pub receiver: mpsc::Receiver<Buf>, pub receiver: mpsc::Receiver<Buf>,
} }
impl CoreResource for WorkerChannels {} impl Resource for WorkerChannels {}
/// Wraps deno::Isolate to provide source maps, ops for the CLI, and /// Wraps deno::Isolate to provide source maps, ops for the CLI, and
/// high-level module loading. /// high-level module loading.
@ -374,12 +374,9 @@ mod tests {
worker.execute(source).unwrap(); worker.execute(source).unwrap();
let worker_ = worker.clone(); let worker_ = worker.clone();
let rid = worker.state.rid;
let resource_ = resources::Resource { rid };
tokio::spawn(lazy(move || { tokio::spawn(lazy(move || {
worker.then(move |r| -> Result<(), ()> { worker.then(move |r| -> Result<(), ()> {
resource_.close();
r.unwrap(); r.unwrap();
Ok(()) Ok(())
}) })
@ -413,12 +410,10 @@ mod tests {
.unwrap(); .unwrap();
let rid = worker.state.rid; let rid = worker.state.rid;
let resource = resources::Resource { rid };
let worker_ = worker.clone(); let worker_ = worker.clone();
let worker_future = worker let worker_future = worker
.then(move |r| -> Result<(), ()> { .then(move |r| -> Result<(), ()> {
resource.close();
println!("workers.rs after resource close"); println!("workers.rs after resource close");
r.unwrap(); r.unwrap();
Ok(()) Ok(())