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::result;
10
11/// Specialized Result type used within the crate.
12pub type Result<T> = result::Result<T, Error>;
13
14/// Specialized Error type used within the crate.
15#[derive(Clone, Hash, Debug)]
16pub struct Error {
17	/// The category of the error.
18	pub kind: Kind,
19	/// The message of the error.
20	pub(crate) msg: String,
21}
22
23impl Error {
24	/// Constructs a new error from the kind and the message.
25	pub(crate) fn new(kind: Kind, msg: &str) -> Self {
26		Self { kind, msg: msg.to_owned() }
27	}
28
29	/// Constructs a new error from the underlying structure.
30	pub(crate) fn from_stack(stack: *const ffi::LIBMTP_error_t) -> Option<Self> {
31		if stack.is_null() {
32			return None;
33		}
34
35		let mut stack = stack;
36		let mut err = unsafe { *stack };
37
38		while !err.next.is_null() {
39			stack = err.next;
40			err = unsafe { *stack };
41		}
42
43		let kind = Kind::from_number(err.errornumber)?;
44		let msg = unsafe { ptr_to_string(err.error_text) };
45		Some(Self { kind, msg })
46	}
47}
48
49impl error::Error for Error {}
50
51impl Display for Error {
52	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
53		write!(f, "{}", self.msg)
54	}
55}
56
57impl Default for Error {
58	fn default() -> Self {
59		Self { kind: Default::default(), msg: "Unknown error".to_owned() }
60	}
61}
62
63/// Category for an error used within the crate.
64#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
65pub enum Kind {
66	/// General error.
67	General,
68	/// An error occured at the PTP (Picture Transfer Protocol) layer.
69	PtpLayer,
70	/// An error occured at the USB layer.
71	UsbLayer,
72	/// An error due to memory allocation failure.
73	MemoryAllocation,
74	/// No device is attached.
75	NoDeviceAttached,
76	/// Error due to insufficient space on the storage of the device.
77	StorageFull,
78	/// An error occured while connecting to the device.
79	Connecting,
80	/// The operation was cancelled.
81	Cancelled,
82	/// Unknown error.
83	#[default]
84	Unknown,
85}
86
87impl Kind {
88	/// Constructs an error kind from the underlying structure.
89	pub(crate) fn from_number(n: ffi::LIBMTP_error_number_t) -> Option<Self> {
90		match n {
91			ffi::LIBMTP_error_number_t::None => None,
92			ffi::LIBMTP_error_number_t::General => Some(Self::General),
93			ffi::LIBMTP_error_number_t::PtpLayer => Some(Self::PtpLayer),
94			ffi::LIBMTP_error_number_t::UsbLayer => Some(Self::UsbLayer),
95			ffi::LIBMTP_error_number_t::MemoryAllocation => Some(Self::MemoryAllocation),
96			ffi::LIBMTP_error_number_t::NoDeviceAttached => Some(Self::NoDeviceAttached),
97			ffi::LIBMTP_error_number_t::StorageFull => Some(Self::StorageFull),
98			ffi::LIBMTP_error_number_t::Connecting => Some(Self::Connecting),
99			ffi::LIBMTP_error_number_t::Cancelled => Some(Self::Cancelled),
100		}
101	}
102}