morgana_core/syntax/source/
file.rs

1use anyhow::Result;
2use std::path::PathBuf;
3use stdext::function_name;
4
5use super::{range::Pos, Source};
6
7#[derive(Debug)]
8pub struct FileSource {
9    pub path: PathBuf,
10    content: String,
11    idx: usize,
12    pub line: u32,
13    pub col: u32,
14}
15
16impl FileSource {
17    pub fn new(path: PathBuf) -> Result<Self> {
18        Ok(Self {
19            path: path.clone(),
20            content: std::fs::read_to_string(path)?,
21            idx: 0,
22            line: 1,
23            col: 1,
24        })
25    }
26}
27
28impl Source for FileSource {
29    fn filename(&self) -> Option<String> {
30        log::trace!("{}", function_name!());
31        Some(self.path.file_name().unwrap().to_str().unwrap().to_string())
32    }
33
34    fn eat(&mut self) -> Option<char> {
35        log::trace!("{}", function_name!());
36        let mut chars = self.content[self.idx..].chars();
37        match chars.next() {
38            Some(c) => {
39                if c == '\n' {
40                    self.line += 1;
41                    self.col = 1;
42                } else {
43                    self.col += 1;
44                }
45
46                self.idx += c.len_utf8();
47                Some(c)
48            }
49            None => None,
50        }
51    }
52
53    fn pos(&self) -> Pos {
54        log::trace!("{}", function_name!());
55        Pos {
56            filename: self.filename(),
57            line: self.line,
58            col: self.col,
59        }
60    }
61
62    fn peek(&self) -> Option<char> {
63        log::trace!("{}", function_name!());
64        let mut chars = self.content[self.idx..].chars();
65        chars.next()
66    }
67}
68
69impl TryFrom<PathBuf> for FileSource {
70    type Error = anyhow::Error;
71
72    fn try_from(value: PathBuf) -> std::prelude::v1::Result<Self, Self::Error> {
73        FileSource::new(value)
74    }
75}