1use crate::{SourceText, source::Source};
2use lsp_types::Position;
3use std::range::Range;
4
5#[derive(Clone, Debug, PartialEq, Eq, Hash)]
11pub struct SourceView<'view> {
12    pub(crate) source: &'view SourceText,
13    pub(crate) range: Range<usize>,
14}
15
16impl<'view> From<&'view SourceText> for SourceView<'view> {
17    fn from(value: &'view SourceText) -> Self {
18        Self { source: value, range: Range { start: 0, end: value.len() } }
19    }
20}
21
22impl<'view> Source for SourceView<'view> {
23    fn length(&self) -> usize {
24        self.range.end.saturating_sub(self.range.start)
25    }
26
27    fn get_text_in(&self, range: Range<usize>) -> &str {
28        let start = self.range.start + range.start;
30        let end = self.range.start + range.end;
31
32        let end = end.min(self.range.end);
34
35        self.source.get_text_in((start..end).into())
36    }
37
38    fn offset_to_position(&self, offset: usize) -> Position {
39        let source_offset = self.range.start + offset;
41        self.source.offset_to_position(source_offset)
42    }
43
44    fn position_to_offset(&self, position: Position) -> usize {
45        let source_offset = self.source.position_to_offset(position);
47        source_offset.saturating_sub(self.range.start)
48    }
49}
50
51impl<'view> SourceView<'view> {
52    pub fn view(&self, range: Range<usize>) -> Self {
65        let start = self.range.start + range.start;
66        let end = self.range.start + range.end;
67        Self { source: self.source, range: Range { start, end } }
68    }
69}