passerine/common/source.rs
1use std::{
2 path::{Path, PathBuf},
3 io::Read,
4 fs::File,
5 rc::Rc,
6};
7
8// TODO: make path optional
9
10/// `Source` represents some literal source code.
11/// Whether a repl session, a file on disk, or some library code.
12/// It's essentially a string with a path, the path serving as the source's name.
13/// Source files without a path point to `./source`,
14/// though this behaviour might change in the future.
15#[derive(Debug, PartialEq, Eq)]
16pub struct Source {
17 pub contents: String,
18 pub path: PathBuf,
19}
20
21impl Source {
22 /// Creates a new `Source` given both an `&str` and a `PathBuf`.
23 /// Note that this function does not check that the contents of the file
24 /// match the source.
25 /// `Source::path` or `Source::source` should be used instead.
26 pub fn new(source: &str, path: &Path) -> Rc<Source> {
27 Rc::new(Source { contents: source.to_string(), path: path.to_owned() })
28 }
29
30 /// Build a `Source` from a path.
31 /// This will read a file to create a new source.
32 pub fn path(path: &Path) -> std::io::Result<Rc<Source>> {
33 let mut source = String::new();
34 let mut file = File::open(path)?;
35 file.read_to_string(&mut source)?;
36
37 Ok(Source::new(&source, path))
38 }
39
40 /// Build an empty `Source` containing just a string.
41 /// Note that this source will point towards `./source`.
42 pub fn source(source: &str) -> Rc<Source> {
43 Source::new(&source.to_string(), &PathBuf::from("./source"))
44 }
45}