xinput/
error.rs

1//! [`Error`], [`Kind`],
2//! [`BAD_ARGUMENTS`], [`BUFFER_TOO_SMALL`], [`DEVICE_NOT_CONNECTED`], [`INVALID_FUNCTION`]
3
4#[cfg(doc)] use crate::*;
5use crate::error_macros::FnContext;
6
7use winresult::{*, ErrorCode};
8
9use core::fmt::{self, Debug, Display, Formatter};
10
11
12
13/// An error returned by some XInput function (or wrapper thereof.)
14#[derive(Clone)]
15pub struct Error(pub(crate) &'static FnContext, pub(crate) Kind);
16
17impl Error {
18    pub(crate) fn method(&self) -> &'static str { self.0.directx_method.unwrap_or(self.0.thindx_method) }
19
20    /// Returns the [`Kind`] of the error
21    pub fn kind(&self) -> Kind { self.1 }
22}
23
24impl Debug   for Error { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "Error({:?}, {:?})", self.method(), self.1) } }
25impl Display for Error { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "{} failed, returning {:?}", self.method(), self.1) } }
26
27impl std::error::Error for Error {}
28impl From<Error> for std::io::Error { fn from(err: Error) -> Self { std::io::Error::new(std::io::ErrorKind::Other, err) } }
29
30impl PartialEq<Error> for ErrorCode { fn eq(&self, other: &Error    ) -> bool { other.kind() == *self } }
31impl PartialEq<Error> for Kind      { fn eq(&self, other: &Error    ) -> bool { other.kind() == *self } }
32impl PartialEq<ErrorCode> for Error { fn eq(&self, other: &ErrorCode) -> bool { self.kind() == *other } }
33impl PartialEq<Kind     > for Error { fn eq(&self, other: &Kind     ) -> bool { self.kind() == *other } }
34
35impl<O, E: PartialEq<Error>> PartialEq<Error> for Result<O, E> { fn eq(&self, other: &Error       ) -> bool { match self.as_ref() { Ok(_) => false, Err(e) => *e == *other } } }
36impl<O, E: PartialEq<Error>> PartialEq<Result<O, E>> for Error { fn eq(&self, other: &Result<O, E>) -> bool { match other.as_ref() { Ok(_) => false, Err(e) => *e == *self } } }
37
38
39
40/// ≈ <code>[winresult]::[ErrorCode]</code> corresponding to <code>[winresult]::[ERROR]::*</code>, but 32-bit, and oriented around XInput error codes.<br>
41#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
42#[repr(transparent)] pub struct Kind(u32);
43
44impl Kind {
45    #[allow(missing_docs)] pub const fn to_u32(self) -> u32 { self.0 }
46
47    pub(crate) const fn new(code: ErrorCode) -> Kind { Kind(code.to_u32()) }
48    pub(crate) const fn from_u32(code: u32) -> Self { Self(code) }
49    pub(crate) fn to_winresult(self) -> winresult::ErrorHResultOrCode { winresult::ErrorHResultOrCode::from(self.0) }
50}
51
52impl Debug for Kind { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { Debug::fmt(&self.to_winresult(), f) } }
53
54impl PartialEq<Kind> for ErrorCode     { fn eq(&self, other: &Kind         ) -> bool { other.to_winresult() == *self } }
55impl PartialEq<Kind> for HResultError  { fn eq(&self, other: &Kind         ) -> bool { other.to_winresult() == *self } }
56impl PartialEq<ErrorCode    > for Kind { fn eq(&self, other: &ErrorCode    ) -> bool { self.to_winresult() == *other } }
57impl PartialEq<HResultError > for Kind { fn eq(&self, other: &HResultError ) -> bool { self.to_winresult() == *other } }
58
59impl<O, E: PartialEq<Kind>> PartialEq<Kind> for Result<O, E> { fn eq(&self, other: &Kind       ) -> bool { match self.as_ref() { Ok(_) => false, Err(e) => *e == *other } } }
60impl<O, E: PartialEq<Kind>> PartialEq<Result<O, E>> for Kind { fn eq(&self, other: &Result<O, E>) -> bool { match other.as_ref() { Ok(_) => false, Err(e) => *e == *self } } }
61
62
63
64/// Invalid `user_index` or [`Flag`] passed to an XInput function.
65pub const BAD_ARGUMENTS : Kind = Kind::new(ERROR::BAD_ARGUMENTS);
66
67/// XAudio2 device IDs are too large (> 4096 characters) for [`get_audio_device_ids`] to read onto the stack.
68pub const BUFFER_TOO_SMALL : Kind = Kind::new(ERROR::BUFFER_TOO_SMALL);
69
70/// COM not initialized.  Only observed being returned from `xinputuap.dll`.
71pub const CO_E_NOTINITIALIZED : Kind = Kind::from_u32(winresult::CO::E_NOTINITIALIZED.to_u32());
72
73/// No gamepad is connected for `user_index`.  N.B. this can be unreliable for [`get_audio_device_ids`].
74pub const DEVICE_NOT_CONNECTED : Kind = Kind::new(ERROR::DEVICE_NOT_CONNECTED);
75
76/// A corresponding XInput function was missing, or XInput itself couldn't be loaded.
77pub const INVALID_FUNCTION : Kind = Kind::new(ERROR::INVALID_FUNCTION);