Skip to main content

ipld_car/
error.rs

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/// Creates a `VfsError` using `kind` and `context`.
104#[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}