mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(codegen)!: Codegen::into_source_text consume Codegen (#6539)
Breaking change. `Codegen::into_source_text` consume `Codegen`, instead of taking the `CodeBuffer` and substituting an empty one. Keeping the `Codegen` alive seems unintuitive, as its state is then out of sync. Consuming the `CodeBuffer` is also marginally cheaper.
This commit is contained in:
parent
7e909a7e6c
commit
c0e9d7eb77
2 changed files with 21 additions and 42 deletions
|
|
@ -1,5 +1,3 @@
|
|||
use std::mem;
|
||||
|
||||
use assert_unchecked::assert_unchecked;
|
||||
|
||||
/// A string builder for constructing source code.
|
||||
|
|
@ -8,8 +6,7 @@ use assert_unchecked::assert_unchecked;
|
|||
/// Essentially same as `String` but with additional methods.
|
||||
///
|
||||
/// Use one of the various `print_*` methods to add text into the buffer.
|
||||
/// When you are done, call [`take_source_text`] or `String::from(code_buffer)`
|
||||
/// to extract the final [`String`].
|
||||
/// When you are done, call [`into_string`] to extract the final [`String`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
|
|
@ -26,10 +23,10 @@ use assert_unchecked::assert_unchecked;
|
|||
/// code.print_str(" console.log('Hello, world!');\n");
|
||||
/// code.print_str("}\n");
|
||||
///
|
||||
/// let source = code.take_source_text();
|
||||
/// let source = code.into_string();
|
||||
/// ```
|
||||
///
|
||||
/// [`take_source_text`]: CodeBuffer::take_source_text
|
||||
/// [`into_string`]: CodeBuffer::into_string
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct CodeBuffer {
|
||||
/// INVARIANT: `buf` is a valid UTF-8 string.
|
||||
|
|
@ -46,7 +43,7 @@ impl CodeBuffer {
|
|||
///
|
||||
/// // use `code` to build new source text
|
||||
/// code.print_str("fn main() { println!(\"Hello, world!\"); }");
|
||||
/// let source_text = code.take_source_text();
|
||||
/// let source_text = code.into_string();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
|
|
@ -187,7 +184,7 @@ impl CodeBuffer {
|
|||
/// code.print_ascii_byte(b'o');
|
||||
/// code.print_ascii_byte(b'o');
|
||||
///
|
||||
/// let source = code.take_source_text();
|
||||
/// let source = code.into_string();
|
||||
/// assert_eq!(source, "foo");
|
||||
/// ```
|
||||
#[inline]
|
||||
|
|
@ -212,7 +209,7 @@ impl CodeBuffer {
|
|||
///
|
||||
/// It is safe for a single call to temporarily result in invalid UTF-8, as long as
|
||||
/// UTF-8 integrity is restored before calls to any other `print_*` method or
|
||||
/// [`take_source_text`]. This lets you, for example, print an 4-byte Unicode character
|
||||
/// [`into_string`]. This lets you, for example, print an 4-byte Unicode character
|
||||
/// using 4 separate calls to this method. However, consider using [`print_bytes_unchecked`]
|
||||
/// instead for that use case.
|
||||
///
|
||||
|
|
@ -237,7 +234,7 @@ impl CodeBuffer {
|
|||
///
|
||||
/// [`print_ascii_byte`]: CodeBuffer::print_ascii_byte
|
||||
/// [`print_char`]: CodeBuffer::print_char
|
||||
/// [`take_source_text`]: CodeBuffer::take_source_text
|
||||
/// [`into_string`]: CodeBuffer::into_string
|
||||
/// [`print_bytes_unchecked`]: CodeBuffer::print_bytes_unchecked
|
||||
#[inline]
|
||||
pub unsafe fn print_byte_unchecked(&mut self, byte: u8) {
|
||||
|
|
@ -382,12 +379,7 @@ impl CodeBuffer {
|
|||
&self.buf
|
||||
}
|
||||
|
||||
/// Convert a buffer into a string of source code, leaving its internal buffer empty.
|
||||
///
|
||||
/// It is safe to re-use a `CodeBuffer` after calling this method, but there is little benefit
|
||||
/// to doing so, as the `CodeBuffer` will be left in an empty state with no backing allocation.
|
||||
///
|
||||
/// You may alternatively use `String::from(code_buffer)`, which may be slightly more efficient.
|
||||
/// Consume buffer and return source code as a `String`.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
|
|
@ -395,18 +387,17 @@ impl CodeBuffer {
|
|||
/// let mut code = CodeBuffer::new();
|
||||
/// code.print_str("console.log('foo');");
|
||||
///
|
||||
/// let source = code.take_source_text();
|
||||
/// let source = code.into_string();
|
||||
/// assert_eq!(source, "console.log('foo');");
|
||||
/// assert!(code.is_empty());
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn take_source_text(&mut self) -> String {
|
||||
pub fn into_string(self) -> String {
|
||||
if cfg!(debug_assertions) {
|
||||
String::from_utf8(mem::take(&mut self.buf)).unwrap()
|
||||
String::from_utf8(self.buf).unwrap()
|
||||
} else {
|
||||
// SAFETY: All methods of `CodeBuffer` ensure `buf` is valid UTF-8
|
||||
unsafe { String::from_utf8_unchecked(mem::take(&mut self.buf)) }
|
||||
unsafe { String::from_utf8_unchecked(self.buf) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -420,13 +411,8 @@ impl AsRef<[u8]> for CodeBuffer {
|
|||
|
||||
impl From<CodeBuffer> for String {
|
||||
#[inline]
|
||||
fn from(buffer: CodeBuffer) -> Self {
|
||||
if cfg!(debug_assertions) {
|
||||
String::from_utf8(buffer.buf).unwrap()
|
||||
} else {
|
||||
// SAFETY: All methods of `CodeBuffer` ensure `buf` is valid UTF-8
|
||||
unsafe { String::from_utf8_unchecked(buffer.buf) }
|
||||
}
|
||||
fn from(code: CodeBuffer) -> Self {
|
||||
code.into_string()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -452,20 +438,13 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn into_source_string() {
|
||||
fn into_string() {
|
||||
let s = "Hello, world!";
|
||||
let mut code = CodeBuffer::with_capacity(s.len());
|
||||
code.print_str(s);
|
||||
|
||||
let source = code.take_source_text();
|
||||
let source = code.into_string();
|
||||
assert_eq!(source, s);
|
||||
|
||||
// buffer has been emptied
|
||||
assert!(code.is_empty());
|
||||
assert_eq!(code.len(), 0);
|
||||
let empty_slice: &[u8] = &[];
|
||||
assert_eq!(code.as_bytes(), empty_slice);
|
||||
assert_eq!(String::from(code), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -151,13 +151,13 @@ impl<'a> Default for Codegen<'a> {
|
|||
}
|
||||
|
||||
impl<'a> From<Codegen<'a>> for String {
|
||||
fn from(mut val: Codegen<'a>) -> Self {
|
||||
fn from(val: Codegen<'a>) -> Self {
|
||||
val.into_source_text()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Codegen<'a>> for Cow<'a, str> {
|
||||
fn from(mut val: Codegen<'a>) -> Self {
|
||||
fn from(val: Codegen<'a>) -> Self {
|
||||
Cow::Owned(val.into_source_text())
|
||||
}
|
||||
}
|
||||
|
|
@ -215,14 +215,14 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
|
||||
program.print(&mut self, Context::default());
|
||||
let code = self.into_source_text();
|
||||
let code = self.code.into_string();
|
||||
let map = self.sourcemap_builder.map(SourcemapBuilder::into_sourcemap);
|
||||
CodegenReturn { code, map }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn into_source_text(&mut self) -> String {
|
||||
self.code.take_source_text()
|
||||
pub fn into_source_text(self) -> String {
|
||||
self.code.into_string()
|
||||
}
|
||||
|
||||
/// Push a single ASCII byte into the buffer.
|
||||
|
|
|
|||
Loading…
Reference in a new issue