mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Unified file loading errors
This commit is contained in:
parent
0dacb2d151
commit
7fb19d5ef8
12
src/diag.rs
12
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})"),
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
32
src/image.rs
32
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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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")?;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user