diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-06-14 20:07:27 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-06-14 20:07:27 +0200 |
| commit | 7fb19d5ef8dc3b183d7de811e373768de56f7ee8 (patch) | |
| tree | 885a94958e8270615aa57069b4d07db82e534b2c | |
| parent | 0dacb2d151e1790613b324b3051b8ce7aa26a90e (diff) | |
Unified file loading errors
| -rw-r--r-- | src/diag.rs | 12 | ||||
| -rw-r--r-- | src/eval/mod.rs | 7 | ||||
| -rw-r--r-- | src/image.rs | 32 | ||||
| -rw-r--r-- | src/library/graphics/image.rs | 8 | ||||
| -rw-r--r-- | src/main.rs | 5 | ||||
| -rw-r--r-- | src/source.rs | 27 |
6 files changed, 49 insertions, 42 deletions
diff --git a/src/diag.rs b/src/diag.rs index 76cad792..c4438307 100644 --- a/src/diag.rs +++ b/src/diag.rs @@ -1,6 +1,8 @@ //! Diagnostics. use std::fmt::{self, Display, Formatter}; +use std::io; +use std::path::Path; use crate::syntax::{Span, Spanned}; use crate::Context; @@ -134,3 +136,13 @@ pub fn with_alternative(msg: String, alt: &str) -> String { msg } } + +/// Format a file loading failure. +pub fn failed_to_load(target: &str, path: &Path, error: io::Error) -> String { + match error.kind() { + io::ErrorKind::NotFound => { + format!("file not found (searched at {})", path.display()) + } + _ => format!("failed to load {target} ({error})"), + } +} diff --git a/src/eval/mod.rs b/src/eval/mod.rs index b1cf9e0b..e2090cd2 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -967,12 +967,7 @@ impl Eval for IncludeExpr { fn import(vm: &mut Machine, path: &str, span: Span) -> TypResult<Module> { // Load the source file. let full = vm.locate(&path).at(span)?; - let id = vm.ctx.sources.load(&full).map_err(|err| match err.kind() { - std::io::ErrorKind::NotFound => { - error!(span, "file not found (searched at {})", full.display()) - } - _ => error!(span, "failed to load source file ({})", err), - })?; + let id = vm.ctx.sources.load(&full).at(span)?; // Prevent cyclic importing. if vm.route.contains(&id) { diff --git a/src/image.rs b/src/image.rs index 6b21bdd9..8ef404fe 100644 --- a/src/image.rs +++ b/src/image.rs @@ -10,6 +10,7 @@ use std::sync::Arc; use image::io::Reader as ImageReader; use image::{DynamicImage, ImageFormat}; +use crate::diag::{failed_to_load, StrResult}; use crate::loading::{FileHash, Loader}; /// A unique identifier for a loaded image. @@ -60,19 +61,24 @@ impl ImageStore { /// Load and decode an image file from a path relative to the compilation /// environment's root. - pub fn load(&mut self, path: &Path) -> io::Result<ImageId> { - let hash = self.loader.resolve(path)?; - Ok(*match self.files.entry(hash) { - Entry::Occupied(entry) => entry.into_mut(), - Entry::Vacant(entry) => { - let buffer = self.loader.load(path)?; - let ext = path.extension().and_then(OsStr::to_str).unwrap_or_default(); - let image = Image::parse(&buffer, ext)?; - let id = ImageId(self.images.len() as u32); - self.images.push(image); - entry.insert(id) - } - }) + pub fn load(&mut self, path: &Path) -> StrResult<ImageId> { + let mut try_load = || -> io::Result<ImageId> { + let hash = self.loader.resolve(path)?; + Ok(*match self.files.entry(hash) { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => { + let buffer = self.loader.load(path)?; + let ext = + path.extension().and_then(OsStr::to_str).unwrap_or_default(); + let image = Image::parse(&buffer, ext)?; + let id = ImageId(self.images.len() as u32); + self.images.push(image); + entry.insert(id) + } + }) + }; + + try_load().map_err(|err| failed_to_load("image", path, err)) } } diff --git a/src/library/graphics/image.rs b/src/library/graphics/image.rs index 1781eb8a..feb37ae6 100644 --- a/src/library/graphics/image.rs +++ b/src/library/graphics/image.rs @@ -16,13 +16,7 @@ impl ImageNode { args.expect::<Spanned<EcoString>>("path to image file")?; let full = vm.locate(&path).at(span)?; - let id = vm.ctx.images.load(&full).map_err(|err| match err.kind() { - std::io::ErrorKind::NotFound => { - error!(span, "file not found (searched at {})", full.display()) - } - _ => error!(span, "failed to load image ({})", err), - })?; - + let id = vm.ctx.images.load(&full).at(span)?; let width = args.named("width")?; let height = args.named("height")?; diff --git a/src/main.rs b/src/main.rs index 2f31d135..784dbc2d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -206,10 +206,7 @@ fn typeset(command: TypesetCommand) -> StrResult<()> { let mut ctx = Context::new(Arc::new(loader), config.build()); // Load the source file. - let id = ctx - .sources - .load(&command.input) - .map_err(|_| "failed to load source file")?; + let id = ctx.sources.load(&command.input)?; // Typeset. match typst::typeset(&mut ctx, id) { diff --git a/src/source.rs b/src/source.rs index ce837f9e..c299da4f 100644 --- a/src/source.rs +++ b/src/source.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use unscanny::Scanner; -use crate::diag::TypResult; +use crate::diag::{failed_to_load, StrResult, TypResult}; use crate::loading::{FileHash, Loader}; use crate::parse::{is_newline, parse, reparse}; use crate::syntax::ast::Markup; @@ -74,19 +74,22 @@ impl SourceStore { /// /// If there already exists a source file for this path, it is /// [replaced](SourceFile::replace). - pub fn load(&mut self, path: impl AsRef<Path>) -> io::Result<SourceId> { - let path = path.as_ref(); - let hash = self.loader.resolve(path)?; - if let Some(&id) = self.files.get(&hash) { - return Ok(id); - } + pub fn load(&mut self, path: &Path) -> StrResult<SourceId> { + let mut try_load = || -> io::Result<SourceId> { + let hash = self.loader.resolve(path)?; + if let Some(&id) = self.files.get(&hash) { + return Ok(id); + } + + let data = self.loader.load(path)?; + let src = String::from_utf8(data).map_err(|_| { + io::Error::new(io::ErrorKind::InvalidData, "file is not valid utf-8") + })?; - let data = self.loader.load(path)?; - let src = String::from_utf8(data).map_err(|_| { - io::Error::new(io::ErrorKind::InvalidData, "file is not valid utf-8") - })?; + Ok(self.provide(path, src)) + }; - Ok(self.provide(path, src)) + try_load().map_err(|err| failed_to_load("source file", path, err)) } /// Directly provide a source file. |
