cobia/
cape_error.rs

1use crate::C;
2use crate::*;
3
4/// Error description from CAPE-OPEN object
5///
6/// Each CAPE-OPEN interface has an getLastError member function that returns
7/// an error interface for any call that results COBIAERR_CAPEOPENERROR.
8///
9/// This is a smart pointer to manage the error object and call its members.
10
11pub struct CapeError {
12	pub(crate) interface: *mut C::ICapeError,
13}
14
15impl CapeError {
16
17	/// Create a new CapeError from an ICapeError interface pointer.
18	///
19	/// The CapeError object is not typically used directly. Errors
20	/// are managed through the COBIAError object, which also manages
21	/// the CapeError based errors raised by CAPE-OPEN objects.
22	///
23	/// # Arguments
24	///
25	/// * `interface` - A pointer to an ICapeError interface
26	///
27	/// # Safety
28	///
29	/// The interface pointer must be non-null and must point to an object
30	/// that implements the ICapeError interface.
31	///
32	/// # Panics
33	///
34	/// Panics if the interface pointer is null.
35
36	pub fn from_interface_pointer(interface: *mut C::ICapeError) ->  Self {
37		if interface.is_null() {
38			panic!("Null pointer in creation of CapeError");
39		}
40		unsafe {((*(*interface).vTbl).base.addReference.unwrap())((*interface).me)};
41		Self {
42			interface
43		}
44	}
45
46	/// Create a new CapeError from an ICapeError interface pointer without adding a reference.
47	///
48	/// The CapeError object is not typically used directly. Errors
49	/// are managed through the COBIAError object, which also manages
50	/// the CapeError based errors raised by CAPE-OPEN objects.
51	///
52	/// # Arguments
53	///
54	/// * `interface` - A pointer to an ICapeError interface
55	///
56	/// # Safety
57	///
58	/// The interface pointer must be non-null and must point to an object
59	/// that implements the ICapeError interface.
60	///
61	/// # Panics
62	///
63	/// Panics if the interface pointer is null.
64
65	pub fn attach(interface: *mut C::ICapeError) ->  Self {
66		if interface.is_null() {
67			panic!("Null pointer in creation of CapeError");
68		}
69		Self {
70			interface
71		}
72	}
73
74	/// Get the error text
75	///
76	/// Gets the error text from the error interface. The error text
77	/// is descriptive information about the nature of the error.
78
79	pub fn get_error_text(&self) -> Result<String, COBIAError> {
80		let mut s = CapeStringImpl::new();
81		let result = unsafe {
82			((*(*self.interface).vTbl).getErrorText.unwrap())((*self.interface).me,(&s.as_cape_string_out() as *const C::ICapeString).cast_mut())
83		};
84		if result == COBIAERR_NOERROR {
85			Ok(s.as_string())
86		} else {
87			Err(COBIAError::Code(result))
88		}
89	}
90
91	/// Get the error that caused this error.
92	///
93	/// Sometimes an error is casued by another error. If so, the
94	/// error that causes this error is available through this function.
95
96	pub fn get_cause(&self) -> Option<CapeError> {
97		let mut interface: *mut C::ICapeError = std::ptr::null_mut();
98		let result = unsafe {
99			((*(*self.interface).vTbl).getCause.unwrap())(
100				(*self.interface).me,
101				&mut interface as *mut *mut C::ICapeError
102			)
103		};
104		if result != COBIAERR_NOERROR || interface.is_null() {
105			None			
106		} else {
107			Some(CapeError { interface })
108		}
109	}
110
111	/// Get the error source
112	///
113	/// The error source is a descriptive name of the object that
114	/// raised the error. 
115
116	pub fn get_source(&self) -> Result<String, COBIAError> {
117		let mut s = CapeStringImpl::new();
118		let result = unsafe {
119			((*(*self.interface).vTbl).getSource.unwrap())((*self.interface).me,(&s.as_cape_string_out() as *const C::ICapeString).cast_mut())
120		};
121		if result == COBIAERR_NOERROR {
122			Ok(s.as_string())
123		} else {
124			Err(COBIAError::Code(result))
125		}
126	}
127
128	/// Get the error scope
129	///
130	/// The error scope is the function that was being executed when
131	/// the error was raised.
132
133	pub fn get_scope(&self) -> Result<String, COBIAError> {
134		let mut s = CapeStringImpl::new();
135		let result = unsafe {
136			((*(*self.interface).vTbl).getScope.unwrap())((*self.interface).me,(&s.as_cape_string_out() as *const C::ICapeString).cast_mut())
137		};
138		if result == COBIAERR_NOERROR {
139			Ok(s.as_string())
140		} else {
141			Err(COBIAError::Code(result))
142		}
143	}
144	
145}
146
147/// Display 
148
149impl std::fmt::Display for CapeError {
150
151	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
152		let mut err:Option<CapeError> = Some(self.clone());
153		while let Some(e)=err {
154			match e.get_scope() {
155				Ok(scope) => {
156					match e.get_source() {
157						Ok(source) => {
158							write!(f, "in {} of {}: ", scope, source)?;
159						},
160						_ => {
161							write!(f, "in {}", scope)?;
162						}
163					}
164				},
165				_ => {
166					match e.get_source() {
167						Ok(source) => {
168							write!(f, "{}: ", source)?;
169						},
170						_ => {}
171					}
172				}
173			}
174			match e.get_error_text() {
175				Ok(text) => {
176					write!(f, "{}", text)?;
177				},
178				_ => {
179					write!(f, "Unknown error")?;
180				}
181			}
182			err=e.get_cause();
183			if err.is_some() {
184				write!(f, ", caused by: ")?;
185			}
186		}
187		Ok(())
188	}
189}
190
191/// Release pointer
192///
193/// ICapeError derives from ICobiaBase, which contains
194/// addReference() and release(). The Drop trait calls release.
195
196impl Drop for CapeError {
197	fn drop(&mut self) {
198		unsafe {
199			((*(*self.interface).vTbl).base.release.unwrap())((*self.interface).me);
200		}
201	}
202}
203
204/// Add pointer reference
205///
206/// ICapeError derives from ICobiaBase, which contains
207/// addReference() and release(). The Clone trait calls addReference.
208
209impl Clone for CapeError {
210	fn clone(&self) -> Self {
211		unsafe {
212			((*(*self.interface).vTbl).base.addReference.unwrap())((*self.interface).me);
213		}
214		CapeError {
215			interface: self.interface,
216		}
217	}
218}
219