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}