summaryrefslogtreecommitdiff
path: root/core/resources.rs
diff options
context:
space:
mode:
Diffstat (limited to 'core/resources.rs')
-rw-r--r--core/resources.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/core/resources.rs b/core/resources.rs
new file mode 100644
index 000000000..c3d8b7107
--- /dev/null
+++ b/core/resources.rs
@@ -0,0 +1,84 @@
+// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
+
+// Think of Resources as File Descriptors. They are integers that are allocated by
+// the privileged side of Deno to refer to various rust objects that need to be
+// referenced between multiple ops. For example, network sockets are resources.
+// Resources may or may not correspond to a real operating system file
+// descriptor (hence the different name).
+
+use downcast_rs::Downcast;
+use std;
+use std::any::Any;
+use std::collections::HashMap;
+use std::io::Error;
+use std::io::ErrorKind;
+
+/// ResourceId is Deno's version of a file descriptor. ResourceId is also referred
+/// to as rid in the code base.
+pub type ResourceId = u32;
+
+/// These store Deno's file descriptors. These are not necessarily the operating
+/// system ones.
+type ResourceMap = HashMap<ResourceId, Box<dyn Resource>>;
+
+#[derive(Default)]
+pub struct ResourceTable {
+ map: ResourceMap,
+ next_id: u32,
+}
+
+impl ResourceTable {
+ pub fn get<T: Resource>(&self, rid: ResourceId) -> Result<&T, Error> {
+ let resource = self.map.get(&rid).ok_or_else(bad_resource)?;
+ let resource = &resource.downcast_ref::<T>().ok_or_else(bad_resource)?;
+ Ok(resource)
+ }
+
+ pub fn get_mut<T: Resource>(
+ &mut self,
+ rid: ResourceId,
+ ) -> Result<&mut T, Error> {
+ let resource = self.map.get_mut(&rid).ok_or_else(bad_resource)?;
+ let resource = resource.downcast_mut::<T>().ok_or_else(bad_resource)?;
+ Ok(resource)
+ }
+
+ // TODO: resource id allocation should probably be randomized for security.
+ fn next_rid(&mut self) -> ResourceId {
+ let next_rid = self.next_id;
+ self.next_id += 1;
+ next_rid as ResourceId
+ }
+
+ pub fn add(&mut self, resource: Box<dyn Resource>) -> ResourceId {
+ let rid = self.next_rid();
+ let r = self.map.insert(rid, resource);
+ assert!(r.is_none());
+ rid
+ }
+
+ // close(2) is done by dropping the value. Therefore we just need to remove
+ // the resource from the RESOURCE_TABLE.
+ pub fn close(&mut self, rid: ResourceId) -> Result<(), Error> {
+ let repr = self.map.remove(&rid).ok_or_else(bad_resource)?;
+ // Give resource a chance to cleanup (notify tasks, etc.)
+ repr.close();
+ Ok(())
+ }
+}
+
+/// Abstract type representing resource in Deno.
+pub trait Resource: Downcast + Any + Send {
+ /// Method that allows to cleanup resource.
+ fn close(&self) {}
+
+ fn inspect_repr(&self) -> &str {
+ unimplemented!();
+ }
+}
+impl_downcast!(Resource);
+
+// TODO: probably bad error kind
+pub fn bad_resource() -> Error {
+ Error::new(ErrorKind::NotFound, "bad resource id")
+}