mesh_loader/
error.rs
1use std::io;
2#[cfg(any(feature = "obj", feature = "stl"))]
3use std::{fmt, path::Path};
4
5#[cfg(any(feature = "obj", feature = "stl"))]
6use crate::utils::bytes::{bytecount_naive, memrchr_naive};
7
8#[cfg(feature = "collada")]
9macro_rules! format_err {
10 ($msg:expr $(,)?) => {
11 crate::error::invalid_data($msg)
12 };
13 ($($tt:tt)*) => {
14 crate::error::invalid_data(format!($($tt)*))
15 };
16}
17
18#[cfg(feature = "collada")]
19macro_rules! bail {
20 ($($tt:tt)*) => {
21 return Err(format_err!($($tt)*))
22 };
23}
24
25#[cold]
26pub(crate) fn invalid_data(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
27 let e = e.into();
28 let kind = e
29 .downcast_ref::<io::Error>()
30 .map_or(io::ErrorKind::InvalidData, io::Error::kind);
31 io::Error::new(kind, e)
32}
33
34#[cfg(any(feature = "obj", feature = "stl"))]
35#[cold]
36pub(crate) fn with_location(e: &io::Error, location: &Location<'_>) -> io::Error {
37 io::Error::new(e.kind(), format!("{e} ({location})"))
38}
39
40#[cfg(any(feature = "obj", feature = "stl"))]
41pub(crate) struct Location<'a> {
42 file: Option<&'a Path>,
43 line: usize,
44 column: usize,
45}
46
47#[cfg(any(feature = "obj", feature = "stl"))]
48impl<'a> Location<'a> {
49 #[cold]
50 #[inline(never)]
51 pub(crate) fn find(remaining: usize, start: &[u8], file: Option<&'a Path>) -> Self {
52 let pos = start.len() - remaining;
53 let line = bytecount_naive(b'\n', &start[..pos]) + 1;
54 let column = memrchr_naive(b'\n', &start[..pos]).unwrap_or(pos) + 1;
55 Self {
56 file: file.filter(|&p| p != Path::new("")),
57 line,
58 column,
59 }
60 }
61}
62
63#[cfg(any(feature = "obj", feature = "stl"))]
64impl fmt::Display for Location<'_> {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 if let Some(file) = self.file {
67 write!(f, "{}:{}:{}", file.display(), self.line, self.column)
68 } else {
69 write!(f, "{}:{}", self.line, self.column)
70 }
71 }
72}