1use crate::{bounded_reader::error::BoundedReaderErr, ContentAddressableArchive};
2
3use ciborium::ser::Error as CborSerErr;
4use std::{
5 convert::Infallible,
6 io::{self, IntoInnerError, Read, Seek},
7 path::{Path, PathBuf},
8 sync::{MutexGuard, PoisonError},
9};
10#[cfg(feature = "vfs")]
11use vfs::error::{VfsError, VfsErrorKind};
12
13mod not_found;
14pub use not_found::NotFoundErr;
15mod not_supported;
16pub use not_supported::NotSupportedErr;
17mod invalid;
18pub use invalid::InvalidErr;
19mod dag_pb;
20pub use dag_pb::{DagPbErr, DagPbResult, UnixFsErr};
21mod loop_detected;
22pub use loop_detected::LoopDetectedErr;
23
24pub type Result<T> = std::result::Result<T, Error>;
25
26#[cfg_attr(feature = "std", derive(Debug))]
27#[derive(thiserror::Error)]
28pub enum Error {
29 #[error("More than one block ({0}) on path `{1:?}`")]
30 MoreThanOneMatchOnPath(usize, PathBuf),
31 #[error("File too large")]
32 FileTooLarge,
33 #[error("CAR lock is poisoned")]
34 Poison,
35 #[error("CID codec `{0}` is not supported")]
36 CodecNotSupported(u64),
37
38 #[error(transparent)]
39 LoopDetected(#[from] LoopDetectedErr),
40 #[error(transparent)]
41 Hasher(#[from] libipld::multihash::Error),
42 #[error(transparent)]
43 NotFound(#[from] NotFoundErr),
44 #[error(transparent)]
45 NotSupported(#[from] NotSupportedErr),
46 #[error(transparent)]
47 Invalid(#[from] InvalidErr),
48 #[error(transparent)]
49 Io(#[from] io::Error),
50 #[error(transparent)]
51 BoundedReader(#[from] BoundedReaderErr),
52 #[error(transparent)]
53 DagPb(#[from] DagPbErr),
54}
55
56impl Error {
57 pub fn more_than_one(matches: usize, path: &Path) -> Self {
58 Self::MoreThanOneMatchOnPath(matches, path.to_owned())
59 }
60}
61
62#[cfg(feature = "vfs")]
63impl From<Error> for VfsError {
64 fn from(ce: Error) -> Self {
65 match ce {
66 Error::NotSupported(not_supported) => not_supported.into(),
67 Error::Io(io_err) => VfsErrorKind::IoError(io_err).into(),
68 Error::NotFound(not_found) => not_found.into(),
69 Error::Invalid(invalid) => invalid.into(),
70 e => VfsErrorKind::Other(e.to_string()).into(),
71 }
72 }
73}
74
75impl From<Infallible> for Error {
76 fn from(_: Infallible) -> Self {
77 unreachable!("Infallible error");
78 }
79}
80
81impl<T> From<IntoInnerError<T>> for Error {
82 fn from(inner_err: IntoInnerError<T>) -> Self {
83 Self::Io(inner_err.into())
84 }
85}
86
87impl From<CborSerErr<io::Error>> for Error {
88 fn from(e: CborSerErr<io::Error>) -> Self {
89 match e {
90 CborSerErr::Io(io_err) => Error::Io(io_err),
91 CborSerErr::Value(msg) => Error::Invalid(InvalidErr::CborEnc(msg)),
92 }
93 }
94}
95
96impl<T: Read + Seek> From<PoisonError<MutexGuard<'_, ContentAddressableArchive<T>>>> for Error {
97 #[inline]
98 fn from(_: PoisonError<MutexGuard<'_, ContentAddressableArchive<T>>>) -> Self {
99 Self::Poison
100 }
101}
102
103#[cfg(feature = "vfs")]
105pub(crate) fn vfs_err<S>(kind: VfsErrorKind, context: S) -> VfsError
106where
107 S: std::fmt::Display + Send + Sync + 'static,
108{
109 VfsError::from(kind).with_context(move || context.to_string())
110}