File size: 2,646 Bytes
bee6636
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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<Atom<'a>> for TransformElement<'a> {
	fn from(value: Atom<'a>) -> Self {
		Self::Str(value.as_str())
	}
}

impl From<AssignmentOperator> for TransformElement<'static> {
	fn from(value: AssignmentOperator) -> Self {
		Self::Str(value.as_str())
	}
}

impl From<u32> 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)),+]
    };
}