libmtp/
err.rs

1//! This module provides specialized error types used for error handling.
2
3use crate::convert::ptr_to_string;
4use crate::ffi;
5use std::error;
6use std::fmt;
7use std::fmt::Display;
8use std::fmt::Formatter;
9use std::io;
10use std::result;
11
12/// Specialized Result type used within the crate.
13pub type Result<T> = result::Result<T, Error>;
14
15/// Specialized Error type used within the crate.
16#[derive(Clone, Hash, Debug)]
17pub struct Error {
18	/// The category of the error.
19	kind: ErrorKind,
20	/// The text of the error.
21	text: String,
22}
23
24impl Error {
25	/// Constructs a new error.
26	pub(crate) fn new(kind: ErrorKind, text: &str) -> Self {
27		Self { kind, text: text.to_owned() }
28	}
29
30	/// Constructs a new error.
31	pub(crate) fn from_ffi(ptr: *const ffi::LIBMTP_error_t) -> Option<Self> {
32		if ptr.is_null() {
33			return None;
34		}
35
36		let mut ptr = ptr;
37		let mut err = unsafe { *ptr };
38
39		while !err.next.is_null() {
40			ptr = err.next;
41			err = unsafe { *ptr };
42		}
43
44		let kind = MtpErrorKind::new(err.errornumber)?;
45		let text = unsafe { ptr_to_string(err.error_text) };
46		Some(Self { kind: ErrorKind::Mtp(kind), text })
47	}
48}
49
50impl error::Error for Error {}
51
52impl Display for Error {
53	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
54		write!(f, "{}", self.text)
55	}
56}
57
58#[doc(hidden)]
59impl Default for Error {
60	fn default() -> Self {
61		Self { kind: ErrorKind::default(), text: "Unknown error".to_owned() }
62	}
63}
64
65#[doc(hidden)]
66impl From<io::Error> for Error {
67	fn from(e: io::Error) -> Self {
68		Self::new(ErrorKind::Io, &e.to_string())
69	}
70}
71
72/// Category for an error used within the crate.
73#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
74pub enum ErrorKind {
75	/// An error occured at the MTP (Media Transfer Protocol) layer.
76	Mtp(MtpErrorKind),
77	/// Input/output error.
78	Io,
79	/// Unknown error.
80	Unknown,
81}
82
83/// Category for an error, that occured at the MTP (Media Transfer Protocol) layer.
84#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
85pub enum MtpErrorKind {
86	/// General error.
87	General,
88	/// An error occured at the PTP (Picture Transfer Protocol) layer.
89	Ptp,
90	/// An error occured at the USB layer.
91	Usb,
92	/// An error due to memory allocation failure.
93	MemoryAllocation,
94	/// No device is attached.
95	NoDeviceAttached,
96	/// Error due to insufficient space on the storage of the device.
97	StorageFull,
98	/// An error occured while connecting to the device.
99	Connecting,
100	/// The operation was cancelled.
101	Cancelled,
102}
103
104impl MtpErrorKind {
105	/// Constructs a new error kind.
106	pub(crate) fn new(n: ffi::LIBMTP_error_number_t) -> Option<Self> {
107		match n {
108			ffi::LIBMTP_error_number_t::None => None,
109			ffi::LIBMTP_error_number_t::General => Some(Self::General),
110			ffi::LIBMTP_error_number_t::PtpLayer => Some(Self::Ptp),
111			ffi::LIBMTP_error_number_t::UsbLayer => Some(Self::Usb),
112			ffi::LIBMTP_error_number_t::MemoryAllocation => Some(Self::MemoryAllocation),
113			ffi::LIBMTP_error_number_t::NoDeviceAttached => Some(Self::NoDeviceAttached),
114			ffi::LIBMTP_error_number_t::StorageFull => Some(Self::StorageFull),
115			ffi::LIBMTP_error_number_t::Connecting => Some(Self::Connecting),
116			ffi::LIBMTP_error_number_t::Cancelled => Some(Self::Cancelled),
117		}
118	}
119}
120
121#[doc(hidden)]
122#[allow(clippy::derivable_impls)]
123impl Default for ErrorKind {
124	fn default() -> Self {
125		ErrorKind::Unknown
126	}
127}