1use crate::HRESULT;
7use mssf_com::FabricTypes::FABRIC_ERROR_CODE;
8
9mod errorcode;
10pub use errorcode::ErrorCode;
11
12pub type Result<T> = core::result::Result<T, Error>;
14
15#[derive(Clone, PartialEq)]
21pub struct Error(pub super::HRESULT);
22
23impl Error {
24 pub fn new(code: HRESULT) -> Self {
25 Self(code)
26 }
27
28 pub fn try_as_fabric_error_code(&self) -> std::result::Result<ErrorCode, &str> {
30 ErrorCode::try_from(FABRIC_ERROR_CODE(self.0.0))
31 }
32}
33
34impl From<HRESULT> for Error {
35 fn from(value: HRESULT) -> Self {
36 Self::new(value)
37 }
38}
39
40impl From<FABRIC_ERROR_CODE> for Error {
41 fn from(value: FABRIC_ERROR_CODE) -> Self {
42 Self::new(HRESULT(value.0))
43 }
44}
45
46impl From<Error> for super::WinError {
47 fn from(val: Error) -> Self {
48 super::WinError::from_hresult(val.0)
49 }
50}
51
52impl From<Error> for HRESULT {
53 fn from(value: Error) -> Self {
54 value.0
55 }
56}
57
58impl From<crate::WinError> for Error {
59 fn from(error: crate::WinError) -> Self {
60 Self(error.into())
61 }
62}
63
64impl core::fmt::Debug for Error {
65 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66 let mut debug = fmt.debug_struct("FabricError");
67 let str_code = ErrorCode::try_from(FABRIC_ERROR_CODE(self.0.0)).ok();
68 debug.field("code", &self.0.0);
69 match str_code {
70 Some(c) => debug.field("message", &c),
71 None => debug.field("message", &"unknown fabric error"),
72 };
73
74 debug.finish()
75 }
76}
77
78impl core::fmt::Display for Error {
79 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80 let str_code = ErrorCode::try_from(FABRIC_ERROR_CODE(self.0.0)).ok();
81 match str_code {
82 Some(c) => core::write!(fmt, "{} ({})", c, self.0.0),
83 None => core::write!(fmt, "{}", self.0.0),
84 }
85 }
86}
87
88impl std::error::Error for Error {}
89
90impl From<std::io::Error> for Error {
93 fn from(value: std::io::Error) -> Self {
94 crate::WinError::from(value).into()
96 }
97}
98
99impl From<Error> for std::io::Error {
100 fn from(value: Error) -> Self {
101 Self::from(crate::WinError::from(value))
103 }
104}
105
106impl From<core::num::TryFromIntError> for Error {
107 fn from(value: core::num::TryFromIntError) -> Self {
108 crate::WinError::from(value).into()
110 }
111}
112
113#[cfg(test)]
114mod test {
115
116 use super::{Error, ErrorCode};
117 use crate::HRESULT;
118 use mssf_com::FabricTypes::FABRIC_E_CODE_PACKAGE_NOT_FOUND;
119 use windows_core::Win32::Foundation::{E_ACCESSDENIED, E_POINTER};
120
121 #[test]
122 fn test_fabric_error() {
123 let fe = Error::from(FABRIC_E_CODE_PACKAGE_NOT_FOUND);
124 assert_eq!(
126 format!("{fe:?}"),
127 "FabricError { code: -2147017733, message: FABRIC_E_CODE_PACKAGE_NOT_FOUND }"
128 );
129 assert_eq!(
131 format!("{fe}"),
132 "FABRIC_E_CODE_PACKAGE_NOT_FOUND (-2147017733)"
133 );
134 let e = crate::WinError::from(fe.clone());
135 assert_eq!(e.code(), fe.into());
136 let ec = Error::from(e)
137 .try_as_fabric_error_code()
138 .expect("unknown code");
139 assert_eq!(ec, ErrorCode::FABRIC_E_CODE_PACKAGE_NOT_FOUND);
140 }
141
142 #[test]
143 fn test_hresult_error() {
144 let err1: HRESULT = Error::from(ErrorCode::E_ACCESSDENIED).into();
145 let err2 = E_ACCESSDENIED;
146 assert_eq!(err1, err2);
147
148 let e: crate::WinError = ErrorCode::E_POINTER.into();
149 assert_eq!(e, E_POINTER.into());
150
151 const SEC_E_INTERNAL_ERROR: crate::HRESULT = crate::HRESULT(0x80090304_u32 as _);
152 let fe = Error::from(SEC_E_INTERNAL_ERROR);
154 assert_eq!(format!("{fe}"), "-2146893052");
156 assert_eq!(
157 format!("{fe:?}"),
158 "FabricError { code: -2146893052, message: \"unknown fabric error\" }"
159 );
160 }
161}