#![expect(clippy::inline_always)]
use oxc_data_structures::code_buffer::CodeBuffer;
mod blanket;
mod config;
mod formatter;
mod primitives;
mod sequences;
mod strings;
mod structs;
use config::{Config, ConfigJS, ConfigTS};
use formatter::{CompactFormatter, Formatter, PrettyFormatter};
use sequences::ESTreeSequenceSerializer;
use structs::ESTreeStructSerializer;
pub use sequences::SequenceSerializer;
pub use strings::{JsonSafeString, LoneSurrogatesString};
pub use structs::{FlatStructSerializer, StructSerializer};
pub trait ESTree {
fn serialize<S: Serializer>(&self, serializer: S);
}
#[expect(private_bounds)]
pub trait Serializer: SerializerPrivate {
const INCLUDE_TS_FIELDS: bool;
type StructSerializer: StructSerializer;
type SequenceSerializer: SequenceSerializer;
fn serialize_struct(self) -> Self::StructSerializer;
fn serialize_sequence(self) -> Self::SequenceSerializer;
}
trait SerializerPrivate: Sized {
type Formatter: Formatter;
fn buffer_mut(&mut self) -> &mut CodeBuffer;
fn buffer_and_formatter_mut(&mut self) -> (&mut CodeBuffer, &mut Self::Formatter);
}
pub type CompactTSSerializer = ESTreeSerializer<ConfigTS, CompactFormatter>;
pub type CompactJSSerializer = ESTreeSerializer<ConfigJS, CompactFormatter>;
pub type PrettyTSSerializer = ESTreeSerializer<ConfigTS, PrettyFormatter>;
pub type PrettyJSSerializer = ESTreeSerializer<ConfigJS, PrettyFormatter>;
pub struct ESTreeSerializer<C: Config, F: Formatter> {
buffer: CodeBuffer,
formatter: F,
#[expect(unused)]
config: C,
}
impl<C: Config, F: Formatter> ESTreeSerializer<C, F> {
pub fn new() -> Self {
Self { buffer: CodeBuffer::new(), formatter: F::new(), config: C::new() }
}
pub fn with_capacity(capacity: usize) -> Self {
Self { buffer: CodeBuffer::with_capacity(capacity), formatter: F::new(), config: C::new() }
}
pub fn into_string(self) -> String {
self.buffer.into_string()
}
}
impl<C: Config, F: Formatter> Default for ESTreeSerializer<C, F> {
#[inline(always)]
fn default() -> Self {
Self::new()
}
}
impl<'s, C: Config, F: Formatter> Serializer for &'s mut ESTreeSerializer<C, F> {
const INCLUDE_TS_FIELDS: bool = C::INCLUDE_TS_FIELDS;
type StructSerializer = ESTreeStructSerializer<'s, C, F>;
type SequenceSerializer = ESTreeSequenceSerializer<'s, C, F>;
#[inline(always)]
fn serialize_struct(self) -> ESTreeStructSerializer<'s, C, F> {
ESTreeStructSerializer::new(self)
}
#[inline(always)]
fn serialize_sequence(self) -> ESTreeSequenceSerializer<'s, C, F> {
ESTreeSequenceSerializer::new(self)
}
}
impl<C: Config, F: Formatter> SerializerPrivate for &mut ESTreeSerializer<C, F> {
type Formatter = F;
#[inline(always)]
fn buffer_mut(&mut self) -> &mut CodeBuffer {
&mut self.buffer
}
#[inline(always)]
fn buffer_and_formatter_mut(&mut self) -> (&mut CodeBuffer, &mut F) {
(&mut self.buffer, &mut self.formatter)
}
}