morgana_core/syntax/source/
file.rs1use 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}