diff --git a/crates/oxc_estree/Cargo.toml b/crates/oxc_estree/Cargo.toml index bb4373f6003ab..52ae91307a498 100644 --- a/crates/oxc_estree/Cargo.toml +++ b/crates/oxc_estree/Cargo.toml @@ -19,7 +19,7 @@ workspace = true doctest = false [dependencies] -oxc_data_structures = { workspace = true, features = ["code_buffer", "pointer_ext", "stack"], optional = true } +oxc_data_structures = { workspace = true, features = ["code_buffer", "pointer_ext", "slice_iter_ext", "stack"], optional = true } itoa = { workspace = true, optional = true } ryu-js = { workspace = true, optional = true } diff --git a/crates/oxc_estree/src/serialize/strings.rs b/crates/oxc_estree/src/serialize/strings.rs index a79b522c2d992..91296165bec1f 100644 --- a/crates/oxc_estree/src/serialize/strings.rs +++ b/crates/oxc_estree/src/serialize/strings.rs @@ -1,6 +1,8 @@ use std::{num::NonZeroU64, slice}; -use oxc_data_structures::{code_buffer::CodeBuffer, pointer_ext::PointerExt}; +use oxc_data_structures::{ + code_buffer::CodeBuffer, pointer_ext::PointerExt, slice_iter_ext::SliceIterExt, +}; use super::{ESTree, Serializer}; @@ -279,13 +281,13 @@ fn write_str(s: &str, buffer: &mut CodeBuffer) { escape = T::get_escape_for_byte(byte); // Consume bytes before this one. // SAFETY: `found_byte_index < 8` and there are at least 8 bytes remaining in `iter` - unsafe { advance_unchecked(&mut iter, found_byte_index) }; + unsafe { iter.advance_unchecked(found_byte_index) }; break 'inner; } // Consume the whole batch. // SAFETY: There are at least `BATCH_SIZE` bytes remaining in `iter`. - unsafe { advance_unchecked(&mut iter, 8) }; + unsafe { iter.advance_unchecked(8) }; // Go round `'inner` loop again to continue searching } else { @@ -296,7 +298,7 @@ fn write_str(s: &str, buffer: &mut CodeBuffer) { if escape != Escape::__ { // Consume bytes before this one. // SAFETY: `i` is an index of `iter`, so cannot be out of bounds. - unsafe { advance_unchecked(&mut iter, i) }; + unsafe { iter.advance_unchecked(i) }; break 'inner; } } @@ -334,7 +336,7 @@ fn write_str(s: &str, buffer: &mut CodeBuffer) { // Consume the lossy replacement character. // SAFETY: Lossy replacement character is 3 bytes. - unsafe { advance_unchecked(&mut iter, 3) }; + unsafe { iter.advance_unchecked(3) }; let hex = iter.as_slice().get(..4).unwrap(); if hex == b"fffd" { @@ -343,7 +345,7 @@ fn write_str(s: &str, buffer: &mut CodeBuffer) { // Consume `fffd`. // SAFETY: We know next 4 bytes are `fffd`. - unsafe { advance_unchecked(&mut iter, 4) }; + unsafe { iter.advance_unchecked(4) }; // Set `chunk_start_ptr` to after `\u{FFFD}fffd`. // That's a complete UTF-8 sequence, so `chunk_start_ptr` is definitely @@ -366,13 +368,13 @@ fn write_str(s: &str, buffer: &mut CodeBuffer) { // if there weren't at least 4 bytes remaining in `iter`. // We haven't checked that the 4 following bytes are ASCII, but it doesn't matter // whether `iter` is left on a UTF-8 char boundary or not. - unsafe { advance_unchecked(&mut iter, 4) } + unsafe { iter.advance_unchecked(4) } } } else { // Some other unicode character starting with 0xEF. // Consume it and continue the loop. // SAFETY: `0xEF` is always 1st byte in a 3-byte UTF-8 character. - unsafe { advance_unchecked(&mut iter, 3) }; + unsafe { iter.advance_unchecked(3) }; } continue; } @@ -393,7 +395,7 @@ fn write_str(s: &str, buffer: &mut CodeBuffer) { write_char_escape(escape, byte, buffer); // SAFETY: `'inner` loop above ensures `iter` is not at end of string - unsafe { advance_unchecked(&mut iter, 1) }; + unsafe { iter.advance_unchecked(1) }; // Set `chunk_start_ptr` to be after this character. // `escape` is only non-zero for ASCII bytes, except `Escape::LO` which is handled above. @@ -416,22 +418,6 @@ fn write_str(s: &str, buffer: &mut CodeBuffer) { buffer.print_ascii_byte(b'"'); } -/// Advance bytes iterator by `count` bytes. -/// -/// # SAFETY -/// Caller must ensure there are at least `count` bytes remaining in `iter`. -#[inline] -unsafe fn advance_unchecked(iter: &mut slice::Iter, count: usize) { - // Compiler boils this down to just adding `count` to `iter`'s pointer. - // SAFETY: Caller guarantees there are at least `count` bytes remaining in `iter`. - unsafe { - let new_ptr = iter.as_slice().as_ptr().add(count); - let new_len = iter.as_slice().len() - count; - let slice = slice::from_raw_parts(new_ptr, new_len); - *iter = slice.iter(); - }; -} - /// Write escape sequence to `buffer`. fn write_char_escape(escape: Escape, byte: u8, buffer: &mut CodeBuffer) { #[expect(clippy::if_not_else)]