summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/diag.rs12
-rw-r--r--src/eval/mod.rs7
-rw-r--r--src/image.rs32
-rw-r--r--src/library/graphics/image.rs8
-rw-r--r--src/main.rs5
-rw-r--r--src/source.rs27
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.