summaryrefslogtreecommitdiff
path: root/core/resources.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2019-10-23 18:32:28 +0200
committerRy Dahl <ry@tinyclouds.org>2019-10-23 12:32:28 -0400
commit029e8330752c29b8c173b0da41a2a4ec23744151 (patch)
tree7cc8302c1e7173cf72c86cc6f303f156bec4db08 /core/resources.rs
parent7c60ab46643d3190d1734678e085bc304c5f7813 (diff)
core: Add ResourceTable (#3150)
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")
+}