From 5e2beaeddeb784045dd049bfb88b94facd515c83 Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 7 Nov 2021 17:01:52 +0000 Subject: [PATCH] Load files --- Cargo.lock | 57 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 +++ src/main.rs | 1 + src/source.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 src/source.rs diff --git a/Cargo.lock b/Cargo.lock index f0d83c1..f207f14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7" + [[package]] name = "atty" version = "0.2.14" @@ -62,6 +68,16 @@ dependencies = [ "vec_map", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "heck" version = "0.3.3" @@ -194,6 +210,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -203,6 +228,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.1.44" @@ -218,8 +263,11 @@ dependencies = [ name = "today" version = "0.1.0" dependencies = [ + "anyhow", "chrono", + "codespan-reporting", "structopt", + "thiserror", ] [[package]] @@ -274,6 +322,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 9931ec2..d11ccd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,8 @@ version = "0.1.0" edition = "2018" [dependencies] +anyhow = "1.0.45" chrono = "0.4.19" +codespan-reporting = "0.11.1" structopt = "0.3.25" +thiserror = "1.0.30" diff --git a/src/main.rs b/src/main.rs index 887b3bc..7590a92 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use structopt::StructOpt; mod commands; +mod source; #[derive(Debug, StructOpt)] pub struct Opt { diff --git a/src/source.rs b/src/source.rs new file mode 100644 index 0000000..c7fbc6c --- /dev/null +++ b/src/source.rs @@ -0,0 +1,64 @@ +use std::collections::HashMap; +use std::ops::Range; +use std::path::{Path, PathBuf}; +use std::{fs, io}; + +use codespan_reporting::files::SimpleFiles; + +#[derive(Debug, thiserror::Error)] +pub enum LoadFileError { + #[error("file already loaded")] + FileAlreadyLoaded, + #[error("error loading file: {0}")] + IoError(#[from] io::Error), +} + +pub struct SourceFiles { + files: SimpleFiles, + files_by_path: HashMap, +} + +impl SourceFiles { + pub fn new() -> Self { + Self { + files: SimpleFiles::new(), + files_by_path: HashMap::new(), + } + } + + pub fn load(&mut self, path: &Path) -> Result { + let canonical_path = path.canonicalize()?; + if self.files_by_path.contains_key(&canonical_path) { + return Err(LoadFileError::FileAlreadyLoaded); + } + + let name = path.as_os_str().to_string_lossy().into_owned(); + let content = fs::read_to_string(path)?; + let file_id = self.files.add(name, content); + Ok(SourceFile(file_id)) + } + + pub fn content_of(&self, file: SourceFile) -> Option<&str> { + self.files.get(file.0).ok().map(|sf| sf.source() as &str) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct SourceFile(usize); + +impl SourceFile { + pub fn span(&self, range: Range) -> SourceSpan { + SourceSpan { + file: self.0, + start: range.start, + end: range.end, + } + } +} + +#[derive(Clone, Copy, Debug)] +pub struct SourceSpan { + file: usize, + start: usize, + end: usize, +}