summaryrefslogtreecommitdiff
path: root/ext/web/lib.rs
diff options
context:
space:
mode:
authorrandomicon00 <20146907+randomicon00@users.noreply.github.com>2022-05-17 14:52:48 +0100
committerGitHub <noreply@github.com>2022-05-17 19:22:48 +0530
commite58f77e431c7f9404bd76f6b7cf5b6d7841c0b0f (patch)
treeba49dbb466b24c7816ba1424ad11d7292d9340ef /ext/web/lib.rs
parent8879244f72aebd2fd4d3ae34a064ff04069a6b58 (diff)
perf(ext/web): Add fast path for non-streaming TextDecoder (#14217)
Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
Diffstat (limited to 'ext/web/lib.rs')
-rw-r--r--ext/web/lib.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/ext/web/lib.rs b/ext/web/lib.rs
index 0d57bf10e..ae5cf2d80 100644
--- a/ext/web/lib.rs
+++ b/ext/web/lib.rs
@@ -90,6 +90,7 @@ pub fn init<P: TimersPermission + 'static>(
op_base64_atob::decl(),
op_base64_btoa::decl(),
op_encoding_normalize_label::decl(),
+ op_encoding_decode_single::decl(),
op_encoding_new_decoder::decl(),
op_encoding_decode::decl(),
op_encoding_encode_into::decl(),
@@ -216,6 +217,64 @@ fn op_encoding_normalize_label(label: String) -> Result<String, AnyError> {
}
#[op]
+fn op_encoding_decode_single(
+ data: ZeroCopyBuf,
+ options: DecoderOptions,
+) -> Result<U16String, AnyError> {
+ let DecoderOptions {
+ label,
+ ignore_bom,
+ fatal,
+ } = options;
+
+ let encoding = Encoding::for_label(label.as_bytes()).ok_or_else(|| {
+ range_error(format!(
+ "The encoding label provided ('{}') is invalid.",
+ label
+ ))
+ })?;
+
+ let mut decoder = if ignore_bom {
+ encoding.new_decoder_without_bom_handling()
+ } else {
+ encoding.new_decoder_with_bom_removal()
+ };
+
+ let max_buffer_length = decoder
+ .max_utf16_buffer_length(data.len())
+ .ok_or_else(|| range_error("Value too large to decode."))?;
+
+ let mut output = vec![0; max_buffer_length];
+
+ if fatal {
+ let (result, _, written) =
+ decoder.decode_to_utf16_without_replacement(&data, &mut output, true);
+ match result {
+ DecoderResult::InputEmpty => {
+ output.truncate(written);
+ Ok(output.into())
+ }
+ DecoderResult::OutputFull => {
+ Err(range_error("Provided buffer too small."))
+ }
+ DecoderResult::Malformed(_, _) => {
+ Err(type_error("The encoded data is not valid."))
+ }
+ }
+ } else {
+ let (result, _, written, _) =
+ decoder.decode_to_utf16(&data, &mut output, true);
+ match result {
+ CoderResult::InputEmpty => {
+ output.truncate(written);
+ Ok(output.into())
+ }
+ CoderResult::OutputFull => Err(range_error("Provided buffer too small.")),
+ }
+ }
+}
+
+#[op]
fn op_encoding_new_decoder(
state: &mut OpState,
options: DecoderOptions,