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}