use oxc::{ allocator::{Allocator, Vec}, ast::ast::AssignmentOperator, span::{Atom, Span}, }; use smallvec::SmallVec; pub use smallvec as vecimpl; pub enum TransformElement<'a> { Str(&'a str), U32(u32), } impl TransformElement<'_> { fn eval(&self, itoa: &mut itoa::Buffer, buffer: &mut Vec<'_, u8>) -> usize { match self { TransformElement::Str(x) => { buffer.extend_from_slice(x.as_bytes()); x.len() } TransformElement::U32(x) => { let x = itoa.format(*x); buffer.extend_from_slice(x.as_bytes()); x.len() } } } } impl<'a> From<&'a str> for TransformElement<'a> { fn from(value: &'a str) -> Self { Self::Str(value) } } impl<'a> From<&&'a str> for TransformElement<'a> { fn from(value: &&'a str) -> Self { Self::Str(value) } } impl<'a> From<&'a String> for TransformElement<'a> { fn from(value: &'a String) -> Self { Self::Str(value) } } impl<'a> From> for TransformElement<'a> { fn from(value: Atom<'a>) -> Self { Self::Str(value.as_str()) } } impl From for TransformElement<'static> { fn from(value: AssignmentOperator) -> Self { Self::Str(value.as_str()) } } impl From for TransformElement<'static> { fn from(value: u32) -> Self { Self::U32(value) } } pub type TransformElements<'a> = SmallVec<[TransformElement<'a>; 8]>; pub enum TransformType { Insert, Replace, } pub trait Transform<'a>: Ord { type ToLowLevelData: 'a; fn span(&self) -> Span; fn into_low_level(self, data: &Self::ToLowLevelData, offset: i32) -> TransformLL<'a>; } pub struct TransformLL<'a> { pub ty: TransformType, pub change: TransformElements<'a>, } impl<'a> TransformLL<'a> { pub fn insert(change: TransformElements<'a>) -> Self { Self { ty: TransformType::Insert, change, } } pub fn replace(change: TransformElements<'a>) -> Self { Self { ty: TransformType::Replace, change, } } pub fn apply(&self, itoa: &mut itoa::Buffer, buffer: &mut Vec<'_, u8>) -> u32 { let mut len = 0; for str in &self.change { len += str.eval(itoa, buffer) as u32; } len } pub fn to_string(&self, itoa: &mut itoa::Buffer, alloc: &Allocator) -> String { let mut vec = Vec::new_in(alloc); self.apply(itoa, &mut vec); std::str::from_utf8(&vec).unwrap().to_string() } } #[macro_export] macro_rules! transforms { [] => { $crate::transform::vecimpl::SmallVec::new() }; [$($change:expr),+] => { $crate::transform::vecimpl::smallvec![$(transform::transform::TransformElement::from($change)),+] }; }