use crate::MagicString;
impl<'text> MagicString<'text> {
pub fn slice(&self, start: usize, end: Option<usize>) -> Result<String, String> {
let original_len = self.source.len();
let end = end.unwrap_or(original_len);
let mut result = String::new();
let mut chunk_idx = Some(self.first_chunk_idx);
while let Some(idx) = chunk_idx {
let chunk = &self.chunks[idx];
if !(chunk.start() > start || chunk.end() <= start) {
break;
}
if chunk.start() < end && chunk.end() >= end {
return Ok(result);
}
chunk_idx = chunk.next;
}
let Some(start_chunk_idx) = chunk_idx else {
return Ok(result);
};
let start_chunk = &self.chunks[start_chunk_idx];
if start_chunk.edited_content.is_some() && start_chunk.start() != start {
return Err(format!("Cannot use replaced character {} as slice start anchor.", start));
}
let mut chunk_idx = Some(start_chunk_idx);
while let Some(idx) = chunk_idx {
let chunk = &self.chunks[idx];
if idx != start_chunk_idx || chunk.start() == start {
for intro in chunk.intro.iter() {
result.push_str(intro.as_ref());
}
}
let contains_end = chunk.start() < end && chunk.end() >= end;
if contains_end && chunk.edited_content.is_some() && chunk.end() != end {
return Err(format!("Cannot use replaced character {} as slice end anchor.", end));
}
let slice_start = if idx == start_chunk_idx { start - chunk.start() } else { 0 };
let content = if let Some(ref edited) = chunk.edited_content {
edited.as_ref()
} else {
chunk.span.text(&self.source)
};
let slice_end = if contains_end { content.len() + end - chunk.end() } else { content.len() };
result.push_str(&content[slice_start..slice_end]);
if !contains_end || chunk.end() == end {
for outro in chunk.outro.iter() {
result.push_str(outro.as_ref());
}
}
if contains_end {
break;
}
chunk_idx = chunk.next;
}
Ok(result)
}
}