summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-09-11 12:04:37 +0200
committerLaurenz <laurmaedje@gmail.com>2023-09-11 12:04:37 +0200
commit921b40cf9cb75c6412e2421130671b08dcf1ee13 (patch)
tree817735ec1d2dabcbb0cd3d38f73f5e2772eb5300 /crates
parent6483d3035bab4df2d644acb738974413977aaa37 (diff)
Forward third-party errors
Better to know something even if it isn't always formatted in the prettiest way
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-cli/Cargo.toml1
-rw-r--r--crates/typst-cli/src/compile.rs14
-rw-r--r--crates/typst-cli/src/main.rs2
-rw-r--r--crates/typst-cli/src/package.rs8
-rw-r--r--crates/typst-cli/src/query.rs4
-rw-r--r--crates/typst-cli/src/tracing.rs4
-rw-r--r--crates/typst-cli/src/update.rs26
-rw-r--r--crates/typst-cli/src/watch.rs7
-rw-r--r--crates/typst-library/src/compute/data.rs53
-rw-r--r--crates/typst-library/src/meta/bibliography.rs4
-rw-r--r--crates/typst-library/src/text/raw.rs9
-rw-r--r--crates/typst/src/diag.rs62
-rw-r--r--crates/typst/src/eval/datetime.rs7
-rw-r--r--crates/typst/src/eval/plugin.rs2
-rw-r--r--crates/typst/src/image.rs8
15 files changed, 114 insertions, 97 deletions
diff --git a/crates/typst-cli/Cargo.toml b/crates/typst-cli/Cargo.toml
index 4b167651..d2418307 100644
--- a/crates/typst-cli/Cargo.toml
+++ b/crates/typst-cli/Cargo.toml
@@ -26,6 +26,7 @@ chrono = { version = "0.4.24", default-features = false, features = ["clock", "s
clap = { version = "4.2.4", features = ["derive", "env"] }
codespan-reporting = "0.11"
comemo = "0.3"
+ecow = "0.1.1"
dirs = "5"
flate2 = "1"
inferno = "0.11.15"
diff --git a/crates/typst-cli/src/compile.rs b/crates/typst-cli/src/compile.rs
index c4800171..8cec8953 100644
--- a/crates/typst-cli/src/compile.rs
+++ b/crates/typst-cli/src/compile.rs
@@ -93,7 +93,7 @@ pub fn compile_once(
}
print_diagnostics(world, &[], &warnings, command.common.diagnostic_format)
- .map_err(|_| "failed to print diagnostics")?;
+ .map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;
if let Some(open) = command.open.take() {
open_file(open.as_deref(), &command.output())?;
@@ -115,7 +115,7 @@ pub fn compile_once(
&warnings,
command.common.diagnostic_format,
)
- .map_err(|_| "failed to print diagnostics")?;
+ .map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;
}
}
@@ -135,7 +135,8 @@ fn export(document: &Document, command: &CompileCommand) -> StrResult<()> {
fn export_pdf(document: &Document, command: &CompileCommand) -> StrResult<()> {
let output = command.output();
let buffer = typst::export::pdf(document);
- fs::write(output, buffer).map_err(|_| "failed to write PDF file")?;
+ fs::write(output, buffer)
+ .map_err(|err| eco_format!("failed to write PDF file ({err})"))?;
Ok(())
}
@@ -176,11 +177,14 @@ fn export_image(
ImageExportFormat::Png => {
let pixmap =
typst::export::render(frame, command.ppi / 72.0, Color::WHITE);
- pixmap.save_png(path).map_err(|_| "failed to write PNG file")?;
+ pixmap
+ .save_png(path)
+ .map_err(|err| eco_format!("failed to write PNG file ({err})"))?;
}
ImageExportFormat::Svg => {
let svg = typst::export::svg(frame);
- fs::write(path, svg).map_err(|_| "failed to write SVG file")?;
+ fs::write(path, svg)
+ .map_err(|err| eco_format!("failed to write SVG file ({err})"))?;
}
}
}
diff --git a/crates/typst-cli/src/main.rs b/crates/typst-cli/src/main.rs
index a6e60e5b..c5cfd514 100644
--- a/crates/typst-cli/src/main.rs
+++ b/crates/typst-cli/src/main.rs
@@ -35,7 +35,7 @@ fn main() -> ExitCode {
let _guard = match crate::tracing::setup_tracing(&ARGS) {
Ok(guard) => guard,
Err(err) => {
- eprintln!("failed to initialize tracing {}", err);
+ eprintln!("failed to initialize tracing ({err})");
None
}
};
diff --git a/crates/typst-cli/src/package.rs b/crates/typst-cli/src/package.rs
index bec86516..51a8e4bc 100644
--- a/crates/typst-cli/src/package.rs
+++ b/crates/typst-cli/src/package.rs
@@ -3,6 +3,7 @@ use std::io::{self, Write};
use std::path::{Path, PathBuf};
use codespan_reporting::term::{self, termcolor};
+use ecow::eco_format;
use termcolor::WriteColor;
use typst::diag::{PackageError, PackageResult};
use typst::syntax::PackageSpec;
@@ -50,18 +51,19 @@ fn download_package(spec: &PackageSpec, package_dir: &Path) -> PackageResult<()>
);
print_downloading(spec).unwrap();
+
let data = match download_with_progress(&url) {
Ok(data) => data,
Err(ureq::Error::Status(404, _)) => {
return Err(PackageError::NotFound(spec.clone()))
}
- Err(_) => return Err(PackageError::NetworkFailed),
+ Err(err) => return Err(PackageError::NetworkFailed(Some(eco_format!("{err}")))),
};
let decompressed = flate2::read::GzDecoder::new(data.as_slice());
- tar::Archive::new(decompressed).unpack(package_dir).map_err(|_| {
+ tar::Archive::new(decompressed).unpack(package_dir).map_err(|err| {
fs::remove_dir_all(package_dir).ok();
- PackageError::MalformedArchive
+ PackageError::MalformedArchive(Some(eco_format!("{err}")))
})
}
diff --git a/crates/typst-cli/src/query.rs b/crates/typst-cli/src/query.rs
index 68cf3319..55f04fe8 100644
--- a/crates/typst-cli/src/query.rs
+++ b/crates/typst-cli/src/query.rs
@@ -31,7 +31,7 @@ pub fn query(command: &QueryCommand) -> StrResult<()> {
let serialized = format(data, command)?;
println!("{serialized}");
print_diagnostics(&world, &[], &warnings, command.common.diagnostic_format)
- .map_err(|_| "failed to print diagnostics")?;
+ .map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;
}
// Print diagnostics.
@@ -43,7 +43,7 @@ pub fn query(command: &QueryCommand) -> StrResult<()> {
&warnings,
command.common.diagnostic_format,
)
- .map_err(|_| "failed to print diagnostics")?;
+ .map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;
}
}
diff --git a/crates/typst-cli/src/tracing.rs b/crates/typst-cli/src/tracing.rs
index 80c2ff65..c01efd6d 100644
--- a/crates/typst-cli/src/tracing.rs
+++ b/crates/typst-cli/src/tracing.rs
@@ -128,10 +128,10 @@ impl TracingGuard {
impl Drop for TracingGuard {
fn drop(&mut self) {
if !std::thread::panicking() {
- if let Err(e) = self.finish() {
+ if let Err(err) = self.finish() {
// Since we are finished, we cannot rely on tracing to log the
// error.
- eprintln!("failed to flush tracing flamegraph: {e}");
+ eprintln!("failed to flush tracing flamegraph ({err})");
}
}
}
diff --git a/crates/typst-cli/src/update.rs b/crates/typst-cli/src/update.rs
index 562d7d2d..95418d03 100644
--- a/crates/typst-cli/src/update.rs
+++ b/crates/typst-cli/src/update.rs
@@ -51,15 +51,15 @@ pub fn update(command: &UpdateCommand) -> StrResult<()> {
return self_replace::self_replace(&backup_path)
.and_then(|_| fs::remove_file(&backup_path))
- .map_err(|err| eco_format!("failed to revert to backup: {err}"));
+ .map_err(|err| eco_format!("failed to revert to backup ({err})"));
}
let current_exe = env::current_exe().map_err(|err| {
- eco_format!("failed to locate path of the running executable: {err}")
+ eco_format!("failed to locate path of the running executable ({err})")
})?;
fs::copy(current_exe, &backup_path)
- .map_err(|err| eco_format!("failed to create backup: {err}"))?;
+ .map_err(|err| eco_format!("failed to create backup ({err})"))?;
let release = Release::from_tag(command.version.as_ref())?;
if !update_needed(&release)? && !command.force {
@@ -69,14 +69,14 @@ pub fn update(command: &UpdateCommand) -> StrResult<()> {
let binary_data = release.download_binary(needed_asset()?)?;
let mut temp_exe = NamedTempFile::new()
- .map_err(|err| eco_format!("failed to create temporary file: {err}"))?;
+ .map_err(|err| eco_format!("failed to create temporary file ({err})"))?;
temp_exe
.write_all(&binary_data)
- .map_err(|err| eco_format!("failed to write binary data: {err}"))?;
+ .map_err(|err| eco_format!("failed to write binary data ({err})"))?;
self_replace::self_replace(&temp_exe).map_err(|err| {
fs::remove_file(&temp_exe).ok();
- eco_format!("failed to self-replace running executable: {err}")
+ eco_format!("failed to self-replace running executable ({err})")
})
}
@@ -118,7 +118,7 @@ impl Release {
Err(ureq::Error::Status(404, _)) => {
bail!("release not found (searched at {url})")
}
- Err(_) => bail!("failed to download release (network failed)"),
+ Err(err) => bail!("failed to download release ({err})"),
}
}
@@ -138,7 +138,7 @@ impl Release {
Err(ureq::Error::Status(404, _)) => {
bail!("asset not found (searched for {})", asset.name);
}
- Err(_) => bail!("failed to load asset (network failed)"),
+ Err(err) => bail!("failed to download asset ({err})"),
};
if asset_name.contains("windows") {
@@ -152,7 +152,7 @@ impl Release {
/// Extract the Typst binary from a ZIP archive.
fn extract_binary_from_zip(data: &[u8], asset_name: &str) -> StrResult<Vec<u8>> {
let mut archive = ZipArchive::new(Cursor::new(data))
- .map_err(|err| eco_format!("failed to extract ZIP archive: {err}"))?;
+ .map_err(|err| eco_format!("failed to extract ZIP archive ({err})"))?;
let mut file = archive
.by_name(&format!("{asset_name}/typst.exe"))
@@ -160,7 +160,7 @@ fn extract_binary_from_zip(data: &[u8], asset_name: &str) -> StrResult<Vec<u8>>
let mut buffer = vec![];
file.read_to_end(&mut buffer).map_err(|err| {
- eco_format!("failed to read binary data from ZIP archive: {err}")
+ eco_format!("failed to read binary data from ZIP archive ({err})")
})?;
Ok(buffer)
@@ -172,14 +172,14 @@ fn extract_binary_from_tar_xz(data: &[u8]) -> StrResult<Vec<u8>> {
let mut file = archive
.entries()
- .map_err(|err| eco_format!("failed to extract tar.xz archive: {err}"))?
+ .map_err(|err| eco_format!("failed to extract tar.xz archive ({err})"))?
.filter_map(Result::ok)
.find(|e| e.path().unwrap_or_default().ends_with("typst"))
.ok_or("tar.xz archive did not contain Typst binary")?;
let mut buffer = vec![];
file.read_to_end(&mut buffer).map_err(|err| {
- eco_format!("failed to read binary data from tar.xz archive: {err}")
+ eco_format!("failed to read binary data from tar.xz archive ({err})")
})?;
Ok(buffer)
@@ -235,7 +235,7 @@ fn backup_path() -> StrResult<PathBuf> {
let backup_dir = root_backup_dir.join("typst");
fs::create_dir_all(&backup_dir)
- .map_err(|err| eco_format!("failed to create backup directory: {err}"))?;
+ .map_err(|err| eco_format!("failed to create backup directory ({err})"))?;
Ok(backup_dir.join("typst_backup.part"))
}
diff --git a/crates/typst-cli/src/watch.rs b/crates/typst-cli/src/watch.rs
index b320c651..f53cb5fd 100644
--- a/crates/typst-cli/src/watch.rs
+++ b/crates/typst-cli/src/watch.rs
@@ -25,7 +25,7 @@ pub fn watch(mut command: CompileCommand) -> StrResult<()> {
// Setup file watching.
let (tx, rx) = std::sync::mpsc::channel();
let mut watcher = RecommendedWatcher::new(tx, notify::Config::default())
- .map_err(|_| "failed to setup file watching")?;
+ .map_err(|err| eco_format!("failed to setup file watching ({err})"))?;
// Watch all the files that are used by the input file and its dependencies.
watch_dependencies(&mut world, &mut watcher, HashSet::new())?;
@@ -41,7 +41,8 @@ pub fn watch(mut command: CompileCommand) -> StrResult<()> {
.into_iter()
.chain(std::iter::from_fn(|| rx.recv_timeout(timeout).ok()))
{
- let event = event.map_err(|_| "failed to watch directory")?;
+ let event =
+ event.map_err(|err| eco_format!("failed to watch directory ({err})"))?;
// Workaround for notify-rs' implicit unwatch on remove/rename
// (triggered by some editors when saving files) with the inotify
@@ -94,7 +95,7 @@ fn watch_dependencies(
tracing::info!("Watching {}", path.display());
watcher
.watch(path, RecursiveMode::NonRecursive)
- .map_err(|_| eco_format!("failed to watch {path:?}"))?;
+ .map_err(|err| eco_format!("failed to watch {path:?} ({err})"))?;
}
}
diff --git a/crates/typst-library/src/compute/data.rs b/crates/typst-library/src/compute/data.rs
index 92c462e6..222b14d3 100644
--- a/crates/typst-library/src/compute/data.rs
+++ b/crates/typst-library/src/compute/data.rs
@@ -1,5 +1,6 @@
use typst::diag::{format_xml_like_error, FileError};
use typst::eval::Bytes;
+use typst::syntax::is_newline;
use crate::prelude::*;
@@ -197,15 +198,16 @@ cast! {
}
/// Format the user-facing CSV error message.
-fn format_csv_error(error: csv::Error, line: usize) -> EcoString {
- match error.kind() {
+fn format_csv_error(err: csv::Error, line: usize) -> EcoString {
+ match err.kind() {
csv::ErrorKind::Utf8 { .. } => "file is not valid utf-8".into(),
csv::ErrorKind::UnequalLengths { expected_len, len, .. } => {
eco_format!(
- "failed to parse csv file: found {len} instead of {expected_len} fields in line {line}"
+ "failed to parse CSV (found {len} instead of \
+ {expected_len} fields in line {line})"
)
}
- _ => "failed to parse csv file".into(),
+ _ => eco_format!("failed to parse CSV ({err})"),
}
}
@@ -278,7 +280,7 @@ pub fn json_decode(
) -> SourceResult<Value> {
let Spanned { v: data, span } = data;
serde_json::from_slice(data.as_slice())
- .map_err(format_json_error)
+ .map_err(|err| eco_format!("failed to parse JSON ({err})"))
.at(span)
}
@@ -302,16 +304,10 @@ pub fn json_encode(
serde_json::to_string(&value)
}
.map(|v| v.into())
- .map_err(|e| eco_format!("failed to encode value as json: {e}"))
+ .map_err(|err| eco_format!("failed to encode value as JSON ({err})"))
.at(span)
}
-/// Format the user-facing JSON error message.
-fn format_json_error(error: serde_json::Error) -> EcoString {
- assert!(error.is_syntax() || error.is_eof());
- eco_format!("failed to parse json file: syntax error in line {}", error.line())
-}
-
/// Reads structured data from a TOML file.
///
/// The file must contain a valid TOML table. TOML tables will be converted into
@@ -366,7 +362,9 @@ pub fn toml_decode(
let raw = std::str::from_utf8(data.as_slice())
.map_err(|_| "file is not valid utf-8")
.at(span)?;
- toml::from_str(raw).map_err(format_toml_error).at(span)
+ toml::from_str(raw)
+ .map_err(|err| format_toml_error(err, raw))
+ .at(span)
}
/// Encodes structured data into a TOML string.
@@ -385,21 +383,21 @@ pub fn toml_encode(
let Spanned { v: value, span } = value;
if pretty { toml::to_string_pretty(&value) } else { toml::to_string(&value) }
.map(|v| v.into())
- .map_err(|e| eco_format!("failed to encode value as toml: {e}"))
+ .map_err(|err| eco_format!("failed to encode value as TOML ({err})"))
.at(span)
}
/// Format the user-facing TOML error message.
-fn format_toml_error(error: toml::de::Error) -> EcoString {
- if let Some(range) = error.span() {
+fn format_toml_error(error: toml::de::Error, raw: &str) -> EcoString {
+ if let Some(head) = error.span().and_then(|range| raw.get(..range.start)) {
+ let line = head.lines().count();
+ let column = 1 + head.chars().rev().take_while(|&c| !is_newline(c)).count();
eco_format!(
- "failed to parse toml file: {}, index {}-{}",
+ "failed to parse TOML ({} at line {line} column {column})",
error.message(),
- range.start,
- range.end
)
} else {
- eco_format!("failed to parse toml file: {}", error.message())
+ eco_format!("failed to parse TOML ({})", error.message())
}
}
@@ -464,7 +462,7 @@ pub fn yaml_decode(
) -> SourceResult<Value> {
let Spanned { v: data, span } = data;
serde_yaml::from_slice(data.as_slice())
- .map_err(format_yaml_error)
+ .map_err(|err| eco_format!("failed to parse YAML ({err})"))
.at(span)
}
@@ -480,15 +478,10 @@ pub fn yaml_encode(
let Spanned { v: value, span } = value;
serde_yaml::to_string(&value)
.map(|v| v.into())
- .map_err(|e| eco_format!("failed to encode value as yaml: {e}"))
+ .map_err(|err| eco_format!("failed to encode value as YAML ({err})"))
.at(span)
}
-/// Format the user-facing YAML error message.
-fn format_yaml_error(error: serde_yaml::Error) -> EcoString {
- eco_format!("failed to parse yaml file: {}", error.to_string().trim())
-}
-
/// Reads structured data from a CBOR file.
///
/// The file must contain a valid cbor serialization. Mappings will be
@@ -529,7 +522,7 @@ pub fn cbor_decode(
) -> SourceResult<Value> {
let Spanned { v: data, span } = data;
ciborium::from_reader(data.as_slice())
- .map_err(|e| eco_format!("failed to parse cbor: {e}"))
+ .map_err(|err| eco_format!("failed to parse CBOR ({err})"))
.at(span)
}
@@ -546,7 +539,7 @@ pub fn cbor_encode(
let mut res = Vec::new();
ciborium::into_writer(&value, &mut res)
.map(|_| res.into())
- .map_err(|e| eco_format!("failed to encode value as cbor: {e}"))
+ .map_err(|err| eco_format!("failed to encode value as CBOR ({err})"))
.at(span)
}
@@ -661,5 +654,5 @@ fn convert_xml(node: roxmltree::Node) -> Value {
/// Format the user-facing XML error message.
fn format_xml_error(error: roxmltree::Error) -> EcoString {
- format_xml_like_error("xml file", error)
+ format_xml_like_error("XML", error)
}
diff --git a/crates/typst-library/src/meta/bibliography.rs b/crates/typst-library/src/meta/bibliography.rs
index 164b1c11..d871db23 100644
--- a/crates/typst-library/src/meta/bibliography.rs
+++ b/crates/typst-library/src/meta/bibliography.rs
@@ -650,8 +650,8 @@ fn parse_bib(path_str: &str, src: &str) -> StrResult<Vec<hayagriva::Entry>> {
}
/// Format a Hayagriva loading error.
-fn format_hayagriva_error(error: YamlBibliographyError) -> EcoString {
- eco_format!("{error}")
+fn format_hayagriva_error(err: YamlBibliographyError) -> EcoString {
+ eco_format!("{err}")
}
/// Format a BibLaTeX loading error.
diff --git a/crates/typst-library/src/text/raw.rs b/crates/typst-library/src/text/raw.rs
index a9d40414..a5699afd 100644
--- a/crates/typst-library/src/text/raw.rs
+++ b/crates/typst-library/src/text/raw.rs
@@ -485,10 +485,9 @@ fn load_syntaxes(paths: &SyntaxPaths, bytes: &[Bytes]) -> StrResult<Arc<SyntaxSe
// We might have multiple sublime-syntax/yaml files
for (path, bytes) in paths.0.iter().zip(bytes.iter()) {
let src = std::str::from_utf8(bytes).map_err(FileError::from)?;
- out.add(
- SyntaxDefinition::load_from_str(src, false, None)
- .map_err(|e| eco_format!("failed to parse syntax file `{path}`: {e}"))?,
- );
+ out.add(SyntaxDefinition::load_from_str(src, false, None).map_err(|err| {
+ eco_format!("failed to parse syntax file `{path}` ({err})")
+ })?);
}
Ok(Arc::new(out.build()))
@@ -528,7 +527,7 @@ fn load_theme(path: EcoString, bytes: Bytes) -> StrResult<Arc<synt::Theme>> {
synt::ThemeSet::load_from_reader(&mut cursor)
.map(Arc::new)
- .map_err(|e| eco_format!("failed to parse theme file `{path}`: {e}"))
+ .map_err(|err| eco_format!("failed to parse theme file `{path}` ({err})"))
}
/// Function to parse the theme argument.
diff --git a/crates/typst/src/diag.rs b/crates/typst/src/diag.rs
index 7c298ec0..a6379d65 100644
--- a/crates/typst/src/diag.rs
+++ b/crates/typst/src/diag.rs
@@ -320,21 +320,23 @@ pub enum FileError {
/// The package the file is part of could not be loaded.
Package(PackageError),
/// Another error.
- Other,
+ ///
+ /// The optional string can give more details, if available.
+ Other(Option<EcoString>),
}
impl FileError {
/// Create a file error from an I/O error.
- pub fn from_io(error: io::Error, path: &Path) -> Self {
- match error.kind() {
+ pub fn from_io(err: io::Error, path: &Path) -> Self {
+ match err.kind() {
io::ErrorKind::NotFound => Self::NotFound(path.into()),
io::ErrorKind::PermissionDenied => Self::AccessDenied,
io::ErrorKind::InvalidData
- if error.to_string().contains("stream did not contain valid UTF-8") =>
+ if err.to_string().contains("stream did not contain valid UTF-8") =>
{
Self::InvalidUtf8
}
- _ => Self::Other,
+ _ => Self::Other(Some(eco_format!("{err}"))),
}
}
}
@@ -352,7 +354,8 @@ impl Display for FileError {
Self::NotSource => f.pad("not a typst source file"),
Self::InvalidUtf8 => f.pad("file is not valid utf-8"),
Self::Package(error) => error.fmt(f),
- Self::Other => f.pad("failed to load file"),
+ Self::Other(Some(err)) => write!(f, "failed to load file ({err})"),
+ Self::Other(None) => f.pad("failed to load file"),
}
}
}
@@ -370,14 +373,14 @@ impl From<FromUtf8Error> for FileError {
}
impl From<PackageError> for FileError {
- fn from(error: PackageError) -> Self {
- Self::Package(error)
+ fn from(err: PackageError) -> Self {
+ Self::Package(err)
}
}
impl From<FileError> for EcoString {
- fn from(error: FileError) -> Self {
- eco_format!("{error}")
+ fn from(err: FileError) -> Self {
+ eco_format!("{err}")
}
}
@@ -385,16 +388,18 @@ impl From<FileError> for EcoString {
pub type PackageResult<T> = Result<T, PackageError>;
/// An error that occured while trying to load a package.
+///
+/// Some variants have an optional string can give more details, if available.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum PackageError {
/// The specified package does not exist.
NotFound(PackageSpec),
/// Failed to retrieve the package through the network.
- NetworkFailed,
+ NetworkFailed(Option<EcoString>),
/// The package archive was malformed.
- MalformedArchive,
+ MalformedArchive(Option<EcoString>),
/// Another error.
- Other,
+ Other(Option<EcoString>),
}
impl std::error::Error for PackageError {}
@@ -405,16 +410,25 @@ impl Display for PackageError {
Self::NotFound(spec) => {
write!(f, "package not found (searched for {spec})",)
}
- Self::NetworkFailed => f.pad("failed to load package (network failed)"),
- Self::MalformedArchive => f.pad("failed to load package (archive malformed)"),
- Self::Other => f.pad("failed to load package"),
+ Self::NetworkFailed(Some(err)) => {
+ write!(f, "failed to download package ({err})")
+ }
+ Self::NetworkFailed(None) => f.pad("failed to download package"),
+ Self::MalformedArchive(Some(err)) => {
+ write!(f, "failed to decompress package ({err})")
+ }
+ Self::MalformedArchive(None) => {
+ f.pad("failed to decompress package (archive malformed)")
+ }
+ Self::Other(Some(err)) => write!(f, "failed to load package ({err})"),
+ Self::Other(None) => f.pad("failed to load package"),
}
}
}
impl From<PackageError> for EcoString {
- fn from(error: PackageError) -> Self {
- eco_format!("{error}")
+ fn from(err: PackageError) -> Self {
+ eco_format!("{err}")
}
}
@@ -423,26 +437,26 @@ pub fn format_xml_like_error(format: &str, error: roxmltree::Error) -> EcoString
match error {
roxmltree::Error::UnexpectedCloseTag { expected, actual, pos } => {
eco_format!(
- "failed to parse {format}: found closing tag '{actual}' \
- instead of '{expected}' in line {}",
+ "failed to parse {format} (found closing tag '{actual}' \
+ instead of '{expected}' in line {})",
pos.row
)
}
roxmltree::Error::UnknownEntityReference(entity, pos) => {
eco_format!(
- "failed to parse {format}: unknown entity '{entity}' in line {}",
+ "failed to parse {format} (unknown entity '{entity}' in line {})",
pos.row
)
}
roxmltree::Error::DuplicatedAttribute(attr, pos) => {
eco_format!(
- "failed to parse {format}: duplicate attribute '{attr}' in line {}",
+ "failed to parse {format}: (duplicate attribute '{attr}' in line {})",
pos.row
)
}
roxmltree::Error::NoRootNode => {
- eco_format!("failed to parse {format}: missing root node")
+ eco_format!("failed to parse {format} (missing root node)")
}
- _ => eco_format!("failed to parse {format}"),
+ err => eco_format!("failed to parse {format} ({err})"),
}
}
diff --git a/crates/typst/src/eval/datetime.rs b/crates/typst/src/eval/datetime.rs
index 96127e9d..ff2d7634 100644
--- a/crates/typst/src/eval/datetime.rs
+++ b/crates/typst/src/eval/datetime.rs
@@ -228,7 +228,10 @@ impl Debug for Datetime {
fn format_time_format_error(error: Format) -> EcoString {
match error {
Format::InvalidComponent(name) => eco_format!("invalid component '{}'", name),
- _ => "failed to format datetime in the requested format".into(),
+ Format::InsufficientTypeInformation { .. } => {
+ "failed to format datetime (insufficient information)".into()
+ }
+ err => eco_format!("failed to format datetime in the requested format ({err})"),
}
}
@@ -263,6 +266,6 @@ fn format_time_invalid_format_description_error(
InvalidFormatDescription::NotSupported { context, what, index, .. } => {
eco_format!("{} is not supported in {} at index {}", what, context, index)
}
- _ => "failed to parse datetime format".into(),
+ err => eco_format!("failed to parse datetime format ({err})"),
}
}
diff --git a/crates/typst/src/eval/plugin.rs b/crates/typst/src/eval/plugin.rs
index 82bb5b6a..7dbc8b3e 100644
--- a/crates/typst/src/eval/plugin.rs
+++ b/crates/typst/src/eval/plugin.rs
@@ -42,7 +42,7 @@ impl Plugin {
pub fn new(bytes: Bytes) -> StrResult<Self> {
let engine = Engine::default();
let module = Module::new(&engine, bytes.as_slice())
- .map_err(|err| format!("failed to load WebAssembly module: {err}"))?;
+ .map_err(|err| format!("failed to load WebAssembly module ({err})"))?;
let mut linker = Linker::new(&engine);
linker
diff --git a/crates/typst/src/image.rs b/crates/typst/src/image.rs
index 83d8f3a7..3c2cae88 100644
--- a/crates/typst/src/image.rs
+++ b/crates/typst/src/image.rs
@@ -8,7 +8,7 @@ use std::rc::Rc;
use std::sync::Arc;
use comemo::{Prehashed, Track, Tracked};
-use ecow::{EcoString, EcoVec};
+use ecow::{eco_format, EcoString, EcoVec};
use image::codecs::gif::GifDecoder;
use image::codecs::jpeg::JpegDecoder;
use image::codecs::png::PngDecoder;
@@ -463,7 +463,7 @@ impl SvgFontLoader for PreparedLoader {
fn format_image_error(error: image::ImageError) -> EcoString {
match error {
image::ImageError::Limits(_) => "file is too large".into(),
- _ => "failed to decode image".into(),
+ err => eco_format!("failed to decode image ({err})"),
}
}
@@ -474,8 +474,8 @@ fn format_usvg_error(error: usvg::Error) -> EcoString {
usvg::Error::MalformedGZip => "file is not compressed correctly".into(),
usvg::Error::ElementsLimitReached => "file is too large".into(),
usvg::Error::InvalidSize => {
- "failed to parse svg: width, height, or viewbox is invalid".into()
+ "failed to parse SVG (width, height, or viewbox is invalid)".into()
}
- usvg::Error::ParsingFailed(error) => format_xml_like_error("svg", error),
+ usvg::Error::ParsingFailed(error) => format_xml_like_error("SVG", error),
}
}