1 //! Extracts a subsequence of a text document, remembering the mapping of ranges
2 //! between original and extracted texts.
3 use std::ops::{self, Sub};
5 use stdx::equal_range_by;
6 use syntax::{TextRange, TextSize};
9 pub(super) struct Injector {
11 ranges: Vec<(TextRange, Option<Delta<TextSize>>)>,
15 pub(super) fn add(&mut self, text: &str, source_range: TextRange) {
16 let len = TextSize::of(text);
17 assert_eq!(len, source_range.len());
18 self.add_impl(text, Some(source_range.start()));
21 pub(super) fn add_unmapped(&mut self, text: &str) {
22 self.add_impl(text, None);
25 fn add_impl(&mut self, text: &str, source: Option<TextSize>) {
26 let len = TextSize::of(text);
27 let target_range = TextRange::at(TextSize::of(&self.buf), len);
28 self.ranges.push((target_range, source.map(|it| Delta::new(target_range.start(), it))));
29 self.buf.push_str(text);
32 pub(super) fn take_text(&mut self) -> String {
33 std::mem::take(&mut self.buf)
36 pub(super) fn map_range_up(&self, range: TextRange) -> impl Iterator<Item = TextRange> + '_ {
37 equal_range_by(&self.ranges, |&(r, _)| TextRange::ordering(r, range)).filter_map(move |i| {
38 let (target_range, delta) = self.ranges[i];
39 let intersection = target_range.intersect(range).unwrap();
40 Some(intersection + delta?)
45 #[derive(Clone, Copy)]
52 fn new(from: T, to: T) -> Delta<T>
54 T: Ord + Sub<Output = T>,
64 impl ops::Add<Delta<TextSize>> for TextSize {
65 type Output = TextSize;
67 fn add(self, rhs: Delta<TextSize>) -> TextSize {
69 Delta::Add(it) => self + it,
70 Delta::Sub(it) => self - it,
75 impl ops::Add<Delta<TextSize>> for TextRange {
76 type Output = TextRange;
78 fn add(self, rhs: Delta<TextSize>) -> TextRange {
79 TextRange::at(self.start() + rhs, self.len())