summaryrefslogtreecommitdiff
path: root/ext/web/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/web/lib.rs')
-rw-r--r--ext/web/lib.rs52
1 files changed, 35 insertions, 17 deletions
diff --git a/ext/web/lib.rs b/ext/web/lib.rs
index cfbcee6e3..7c75a9a28 100644
--- a/ext/web/lib.rs
+++ b/ext/web/lib.rs
@@ -270,7 +270,7 @@ fn op_encoding_decode_single(
#[op]
fn op_encoding_new_decoder(
state: &mut OpState,
- label: String,
+ label: &str,
fatal: bool,
ignore_bom: bool,
) -> Result<ResourceId, AnyError> {
@@ -352,25 +352,43 @@ impl Resource for TextDecoderResource {
}
}
-#[op(v8)]
+#[op]
fn op_encoding_encode_into(
- scope: &mut v8::HandleScope,
- input: serde_v8::Value,
+ input: Cow<'_, str>,
buffer: &mut [u8],
out_buf: &mut [u32],
-) -> Result<(), AnyError> {
- let s = v8::Local::<v8::String>::try_from(input.v8_value)?;
-
- 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(())
+) {
+ // 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();
+
+ // 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());
+
+ // The `read` output parameter is measured in UTF-16 code units.
+ out_buf[0] = match input {
+ // Borrowed Cow strings are zero-copy views into the V8 heap.
+ // Thus, they are guarantee to be SeqOneByteString.
+ Cow::Borrowed(v) => v[..boundary].len() as u32,
+ Cow::Owned(v) => v[..boundary].encode_utf16().count() as u32,
+ };
+ out_buf[1] = boundary as u32;
}
#[op(v8)]