summaryrefslogtreecommitdiff
path: root/ext/web/compression.rs
diff options
context:
space:
mode:
authorLeo Kettmeir <crowlkats@toaxl.com>2022-01-24 18:03:06 +0100
committerGitHub <noreply@github.com>2022-01-24 18:03:06 +0100
commit30ddf436d0d48ce0f9238f1728bc83aa4c6dddad (patch)
tree92cb750fe2a2beaf9b5884530bb3419ddee54cb4 /ext/web/compression.rs
parentae0414fa3581d76af44192567d73dce987c69b9d (diff)
feat(ext/web): add CompressionStream API (#11728)
Co-authored-by: Luca Casonato <hello@lcas.dev> Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
Diffstat (limited to 'ext/web/compression.rs')
-rw-r--r--ext/web/compression.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/ext/web/compression.rs b/ext/web/compression.rs
new file mode 100644
index 000000000..c84db7550
--- /dev/null
+++ b/ext/web/compression.rs
@@ -0,0 +1,104 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+
+use deno_core::error::AnyError;
+use deno_core::OpState;
+use deno_core::Resource;
+use deno_core::ResourceId;
+use deno_core::ZeroCopyBuf;
+use flate2::write::GzDecoder;
+use flate2::write::GzEncoder;
+use flate2::write::ZlibDecoder;
+use flate2::write::ZlibEncoder;
+use flate2::Compression;
+use std::borrow::Cow;
+use std::cell::RefCell;
+use std::io::Write;
+use std::rc::Rc;
+
+#[derive(Debug)]
+struct CompressionResource(RefCell<Inner>);
+
+#[derive(Debug)]
+enum Inner {
+ DeflateDecoder(ZlibDecoder<Vec<u8>>),
+ DeflateEncoder(ZlibEncoder<Vec<u8>>),
+ GzDecoder(GzDecoder<Vec<u8>>),
+ GzEncoder(GzEncoder<Vec<u8>>),
+}
+
+impl Resource for CompressionResource {
+ fn name(&self) -> Cow<str> {
+ "compression".into()
+ }
+}
+
+pub fn op_compression_new(
+ state: &mut OpState,
+ format: String,
+ is_decoder: bool,
+) -> Result<ResourceId, AnyError> {
+ let w = Vec::new();
+ let inner = match (format.as_str(), is_decoder) {
+ ("deflate", true) => Inner::DeflateDecoder(ZlibDecoder::new(w)),
+ ("deflate", false) => {
+ Inner::DeflateEncoder(ZlibEncoder::new(w, Compression::default()))
+ }
+ ("gzip", true) => Inner::GzDecoder(GzDecoder::new(w)),
+ ("gzip", false) => {
+ Inner::GzEncoder(GzEncoder::new(w, Compression::default()))
+ }
+ _ => unreachable!(),
+ };
+ let resource = CompressionResource(RefCell::new(inner));
+ Ok(state.resource_table.add(resource))
+}
+
+pub fn op_compression_write(
+ state: &mut OpState,
+ rid: ResourceId,
+ input: ZeroCopyBuf,
+) -> Result<ZeroCopyBuf, AnyError> {
+ let resource = state.resource_table.get::<CompressionResource>(rid)?;
+ let mut inner = resource.0.borrow_mut();
+ let out: Vec<u8> = match &mut *inner {
+ Inner::DeflateDecoder(d) => {
+ d.write_all(&input)?;
+ d.flush()?;
+ d.get_mut().drain(..)
+ }
+ Inner::DeflateEncoder(d) => {
+ d.write_all(&input)?;
+ d.flush()?;
+ d.get_mut().drain(..)
+ }
+ Inner::GzDecoder(d) => {
+ d.write_all(&input)?;
+ d.flush()?;
+ d.get_mut().drain(..)
+ }
+ Inner::GzEncoder(d) => {
+ d.write_all(&input)?;
+ d.flush()?;
+ d.get_mut().drain(..)
+ }
+ }
+ .collect();
+ Ok(out.into())
+}
+
+pub fn op_compression_finish(
+ state: &mut OpState,
+ rid: ResourceId,
+ _: (),
+) -> Result<ZeroCopyBuf, AnyError> {
+ let resource = state.resource_table.take::<CompressionResource>(rid)?;
+ let resource = Rc::try_unwrap(resource).unwrap();
+ let inner = resource.0.into_inner();
+ let out: Vec<u8> = match inner {
+ Inner::DeflateDecoder(d) => d.finish()?,
+ Inner::DeflateEncoder(d) => d.finish()?,
+ Inner::GzDecoder(d) => d.finish()?,
+ Inner::GzEncoder(d) => d.finish()?,
+ };
+ Ok(out.into())
+}