summaryrefslogtreecommitdiff
path: root/extensions/file/lib.rs
diff options
context:
space:
mode:
authorAndy Hayden <andyhayden1@gmail.com>2021-04-30 12:51:48 -0700
committerGitHub <noreply@github.com>2021-04-30 15:51:48 -0400
commit684c357136fd44f9d5a1b8bb4402400ed1354677 (patch)
treeebc14b1d01b6643dd4d588516692dffc0f8fcb52 /extensions/file/lib.rs
parentabaec7a88e991188d885bede652f35d76ab4f340 (diff)
Rename crate_ops to extensions (#10431)
Diffstat (limited to 'extensions/file/lib.rs')
-rw-r--r--extensions/file/lib.rs120
1 files changed, 120 insertions, 0 deletions
diff --git a/extensions/file/lib.rs b/extensions/file/lib.rs
new file mode 100644
index 000000000..78e3db814
--- /dev/null
+++ b/extensions/file/lib.rs
@@ -0,0 +1,120 @@
+// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+
+use deno_core::error::null_opbuf;
+use deno_core::error::AnyError;
+use deno_core::include_js_files;
+use deno_core::op_sync;
+use deno_core::url::Url;
+use deno_core::Extension;
+use deno_core::ModuleSpecifier;
+use deno_core::ZeroCopyBuf;
+use std::collections::HashMap;
+use std::path::PathBuf;
+use std::sync::Arc;
+use std::sync::Mutex;
+use uuid::Uuid;
+
+#[derive(Debug, Clone)]
+pub struct Blob {
+ pub data: Vec<u8>,
+ pub media_type: String,
+}
+
+pub struct Location(pub Url);
+
+#[derive(Debug, Default, Clone)]
+pub struct BlobUrlStore(Arc<Mutex<HashMap<Url, Blob>>>);
+
+impl BlobUrlStore {
+ pub fn get(&self, mut url: Url) -> Result<Option<Blob>, AnyError> {
+ let blob_store = self.0.lock().unwrap();
+ url.set_fragment(None);
+ Ok(blob_store.get(&url).cloned())
+ }
+
+ pub fn insert(&self, blob: Blob, maybe_location: Option<Url>) -> Url {
+ let origin = if let Some(location) = maybe_location {
+ location.origin().ascii_serialization()
+ } else {
+ "null".to_string()
+ };
+ let id = Uuid::new_v4();
+ let url = Url::parse(&format!("blob:{}/{}", origin, id)).unwrap();
+
+ let mut blob_store = self.0.lock().unwrap();
+ blob_store.insert(url.clone(), blob);
+
+ url
+ }
+
+ pub fn remove(&self, url: &ModuleSpecifier) {
+ let mut blob_store = self.0.lock().unwrap();
+ blob_store.remove(&url);
+ }
+}
+
+pub fn op_file_create_object_url(
+ state: &mut deno_core::OpState,
+ media_type: String,
+ zero_copy: Option<ZeroCopyBuf>,
+) -> Result<String, AnyError> {
+ let data = zero_copy.ok_or_else(null_opbuf)?;
+ let blob = Blob {
+ data: data.to_vec(),
+ media_type,
+ };
+
+ let maybe_location = state.try_borrow::<Location>();
+ let blob_store = state.borrow::<BlobUrlStore>();
+
+ let url =
+ blob_store.insert(blob, maybe_location.map(|location| location.0.clone()));
+
+ Ok(url.to_string())
+}
+
+pub fn op_file_revoke_object_url(
+ state: &mut deno_core::OpState,
+ url: String,
+ _zero_copy: Option<ZeroCopyBuf>,
+) -> Result<(), AnyError> {
+ let url = Url::parse(&url)?;
+ let blob_store = state.borrow::<BlobUrlStore>();
+ blob_store.remove(&url);
+ Ok(())
+}
+
+pub fn init(
+ blob_url_store: BlobUrlStore,
+ maybe_location: Option<Url>,
+) -> Extension {
+ Extension::builder()
+ .js(include_js_files!(
+ prefix "deno:extensions/file",
+ "01_file.js",
+ "02_filereader.js",
+ "03_blob_url.js",
+ ))
+ .ops(vec![
+ (
+ "op_file_create_object_url",
+ op_sync(op_file_create_object_url),
+ ),
+ (
+ "op_file_revoke_object_url",
+ op_sync(op_file_revoke_object_url),
+ ),
+ ])
+ .state(move |state| {
+ state.put(blob_url_store.clone());
+ if let Some(location) = maybe_location.clone() {
+ state.put(Location(location));
+ }
+ Ok(())
+ })
+ .build()
+}
+
+pub fn get_declaration() -> PathBuf {
+ PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_file.d.ts")
+}