mirror of
https://github.com/denoland/deno.git
synced 2025-08-03 18:38:33 +00:00
perf(web): optimize encodeInto() (#15922)
This commit is contained in:
parent
6154188786
commit
5fe660ecd7
5 changed files with 126 additions and 164 deletions
|
@ -10,7 +10,9 @@ use deno_core::error::type_error;
|
|||
use deno_core::error::AnyError;
|
||||
use deno_core::include_js_files;
|
||||
use deno_core::op;
|
||||
use deno_core::serde_v8;
|
||||
use deno_core::url::Url;
|
||||
use deno_core::v8;
|
||||
use deno_core::ByteString;
|
||||
use deno_core::CancelHandle;
|
||||
use deno_core::Extension;
|
||||
|
@ -19,11 +21,11 @@ use deno_core::Resource;
|
|||
use deno_core::ResourceId;
|
||||
use deno_core::U16String;
|
||||
use deno_core::ZeroCopyBuf;
|
||||
|
||||
use encoding_rs::CoderResult;
|
||||
use encoding_rs::Decoder;
|
||||
use encoding_rs::DecoderResult;
|
||||
use encoding_rs::Encoding;
|
||||
use serde::Serialize;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
|
@ -314,46 +316,25 @@ impl Resource for TextDecoderResource {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct EncodeIntoResult {
|
||||
read: usize,
|
||||
written: usize,
|
||||
}
|
||||
|
||||
#[op]
|
||||
#[op(v8)]
|
||||
fn op_encoding_encode_into(
|
||||
input: String,
|
||||
scope: &mut v8::HandleScope,
|
||||
input: serde_v8::Value,
|
||||
buffer: &mut [u8],
|
||||
) -> EncodeIntoResult {
|
||||
// Since `input` is already UTF-8, we can simply find the last UTF-8 code
|
||||
// point boundary from input that fits in `buffer`, and copy the bytes up to
|
||||
// that point.
|
||||
let boundary = if buffer.len() >= input.len() {
|
||||
input.len()
|
||||
} else {
|
||||
let mut boundary = buffer.len();
|
||||
out_buf: &mut [u32],
|
||||
) -> Result<(), AnyError> {
|
||||
let s = v8::Local::<v8::String>::try_from(input.v8_value)?;
|
||||
|
||||
// The maximum length of a UTF-8 code point is 4 bytes.
|
||||
for _ in 0..4 {
|
||||
if input.is_char_boundary(boundary) {
|
||||
break;
|
||||
}
|
||||
debug_assert!(boundary > 0);
|
||||
boundary -= 1;
|
||||
}
|
||||
|
||||
debug_assert!(input.is_char_boundary(boundary));
|
||||
boundary
|
||||
};
|
||||
|
||||
buffer[..boundary].copy_from_slice(input[..boundary].as_bytes());
|
||||
|
||||
EncodeIntoResult {
|
||||
// The `read` output parameter is measured in UTF-16 code units.
|
||||
read: input[..boundary].encode_utf16().count(),
|
||||
written: boundary,
|
||||
}
|
||||
let mut nchars = 0;
|
||||
out_buf[1] = s.write_utf8(
|
||||
scope,
|
||||
buffer,
|
||||
Some(&mut nchars),
|
||||
v8::WriteOptions::NO_NULL_TERMINATION
|
||||
| v8::WriteOptions::REPLACE_INVALID_UTF8,
|
||||
) as u32;
|
||||
out_buf[0] = nchars as u32;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates a [`CancelHandle`] resource that can be used to cancel invocations of certain ops.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue