use super::applicator::{ApplyResult, PatchApplicator};
use super::helpers::dedupe_patches;
use crate::host::error::Result;
use crate::ts_syn::abi::{MappingSegment, Patch, SourceMapping};
pub struct PatchCollector {
runtime_patches: Vec<Patch>,
type_patches: Vec<Patch>,
}
impl PatchCollector {
pub fn new() -> Self {
Self {
runtime_patches: Vec::new(),
type_patches: Vec::new(),
}
}
pub fn add_runtime_patches(&mut self, patches: Vec<Patch>) {
self.runtime_patches.extend(patches);
}
pub fn add_type_patches(&mut self, patches: Vec<Patch>) {
self.type_patches.extend(patches);
}
pub fn has_type_patches(&self) -> bool {
!self.type_patches.is_empty()
}
pub fn has_patches(&self) -> bool {
!self.runtime_patches.is_empty() || !self.type_patches.is_empty()
}
pub fn runtime_patches_count(&self) -> usize {
self.runtime_patches.len()
}
pub fn runtime_patches_slice(&self, start: usize) -> &[Patch] {
&self.runtime_patches[start..]
}
pub fn apply_runtime_patches(&self, source: &str) -> Result<String> {
if self.runtime_patches.is_empty() {
return Ok(source.to_string());
}
let mut patches = self.runtime_patches.clone();
dedupe_patches(&mut patches)?;
let applicator = PatchApplicator::new(source, patches);
applicator.apply()
}
pub fn apply_type_patches(&self, source: &str) -> Result<String> {
if self.type_patches.is_empty() {
return Ok(source.to_string());
}
let mut patches = self.type_patches.clone();
dedupe_patches(&mut patches)?;
let applicator = PatchApplicator::new(source, patches);
applicator.apply()
}
pub fn apply_runtime_patches_with_mapping(
&self,
source: &str,
macro_name: Option<&str>,
) -> Result<ApplyResult> {
if self.runtime_patches.is_empty() {
let source_len = source.len() as u32;
let mut mapping = SourceMapping::new();
if source_len > 0 {
mapping.add_segment(MappingSegment::new(0, source_len, 0, source_len));
}
return Ok(ApplyResult {
code: source.to_string(),
mapping,
});
}
let mut patches = self.runtime_patches.clone();
dedupe_patches(&mut patches)?;
let applicator = PatchApplicator::new(source, patches);
applicator.apply_with_mapping(macro_name)
}
pub fn apply_type_patches_with_mapping(
&self,
source: &str,
macro_name: Option<&str>,
) -> Result<ApplyResult> {
if self.type_patches.is_empty() {
let source_len = source.len() as u32;
let mut mapping = SourceMapping::new();
if source_len > 0 {
mapping.add_segment(MappingSegment::new(0, source_len, 0, source_len));
}
return Ok(ApplyResult {
code: source.to_string(),
mapping,
});
}
let mut patches = self.type_patches.clone();
dedupe_patches(&mut patches)?;
let applicator = PatchApplicator::new(source, patches);
applicator.apply_with_mapping(macro_name)
}
pub fn get_type_patches(&self) -> &Vec<Patch> {
&self.type_patches
}
}
impl Default for PatchCollector {
fn default() -> Self {
Self::new()
}
}