cobia/
cape_error_impl.rs

1use crate::C;
2use crate::*;
3
4/// CAPE-OPEN Error object implementation
5///
6/// This class implements a native CAPE-OPEN error object. The error object
7///  implements ICapeError. This object is constructed when ICapeInterfaceImpl
8///  is asked for its current error.
9
10pub struct CapeErrorImpl {
11	interface: C::ICapeError,
12	text: String,
13	scope: String,
14	source: String,
15	cause: Option<CapeError>, 
16	reference_count: i32,
17}
18
19impl CapeErrorImpl {
20	pub fn new(err: &COBIAError, scope: &str, source: &str) -> *mut C::ICapeError {
21		let mut cause: Option<CapeError>=None;
22		let text = match err {
23			COBIAError::Message(s) => String::from(s),
24			COBIAError::Code(code) => {
25				let mut s = CapeStringImpl::new();
26				let res = unsafe { C::capeGetErrorDescription(*code, (&s.as_cape_string_out() as *const C::ICapeString).cast_mut()) };
27				if res == COBIAERR_NOERROR {
28					s.to_string()
29				} else {
30					format!("COBIA error code: {}", code)
31				}
32			},
33			COBIAError::CAPEOPEN(err) => {
34				cause=err.get_cause();
35				err.get_error_text().unwrap()
36			},
37			COBIAError::MessageWithCause(msg, because) => {
38				cause=Some(because.clone());
39				msg.clone()
40			},
41		};
42		let err_ptr = Box::into_raw(Box::new(CapeErrorImpl { //into_raw locks the object in memory - no need to pin
43			interface: C::ICapeError {
44				vTbl: &CapeErrorImpl::VTABLE as *const C::ICapeError_VTable
45					as *mut C::ICapeError_VTable,
46				me: std::ptr::null_mut(),
47			},
48			text,
49			source: source.to_string(),
50			cause,
51			scope: scope.to_string(),
52			reference_count: 1, //this is the return reference
53		}));
54		unsafe {
55			(*err_ptr).interface.me = (err_ptr as *mut CapeErrorImpl) as *mut std::ffi::c_void;
56			&mut (*err_ptr).interface as *mut C::ICapeError
57		}
58	}
59
60	extern "C" fn add_reference(me: *mut ::std::os::raw::c_void) {
61		let p: *mut CapeErrorImpl = me as *mut CapeErrorImpl;
62		unsafe {
63			(*p).reference_count += 1;
64		}
65	}
66
67	extern "C" fn release(me: *mut ::std::os::raw::c_void) {
68		let p = me as *mut CapeErrorImpl;
69		unsafe {
70			(*p).reference_count -= 1;
71			if (*p).reference_count == 0 {
72				drop(Box::from_raw(p));
73			}
74		}
75	}
76
77	extern "C" fn get_error_text(
78		me: *mut ::std::os::raw::c_void,
79		error_text: *mut C::ICapeString,
80	) -> CapeResult {
81		let p = me as *mut CapeErrorImpl;
82		if error_text.is_null() {
83			COBIAERR_NULLPOINTER
84		} else {
85			let mut error_text=unsafe{*((&error_text as *const *mut crate::C::ICapeString) as *mut *mut crate::C::ICapeString)};
86			let error_text=CapeStringOut::new(&mut error_text);
87			match unsafe { error_text.set_string(&(*p).text) } {
88				Ok(_) => COBIAERR_NOERROR,
89				Err(err) => match err {
90					COBIAError::Code(code) => {
91						return code;
92					}
93					_ => {
94						assert!(false);
95						return COBIAERR_UNKNOWNERROR;
96					}
97				},
98			}
99		}
100	}
101
102	extern "C" fn get_cause(
103		me: *mut ::std::os::raw::c_void,
104		cause: *mut *mut C::ICapeError,
105	) -> CapeResult {
106		let p = me as *mut CapeErrorImpl;
107		if let Some(err) = unsafe { &(*p).cause } {
108			unsafe {
109				let e=err.interface;
110				*cause = e;
111				(*(*e).vTbl).base.addReference.unwrap()((*e).me);
112				COBIAERR_NOERROR
113			}
114		} else {
115			COBIAERR_NOSUCHITEM
116		}
117	}
118
119	extern "C" fn get_source(
120		me: *mut ::std::os::raw::c_void,
121		component_description: *mut C::ICapeString,
122	) -> CapeResult {
123		let p = me as *mut CapeErrorImpl;
124		if component_description.is_null() {
125			COBIAERR_NULLPOINTER
126		} else {
127			let mut component_description=unsafe{*((&component_description as *const *mut crate::C::ICapeString) as *mut *mut crate::C::ICapeString)};
128			let component_description=CapeStringOut::new(&mut component_description);
129			match unsafe { component_description.set_string(&(*p).source) } {
130				Ok(_) => COBIAERR_NOERROR,
131				Err(err) => match err {
132					COBIAError::Code(code) => {
133						return code;
134					}
135					_ => {
136						assert!(false);
137						return COBIAERR_UNKNOWNERROR;
138					}
139				},
140			}
141		}
142	}
143
144	extern "C" fn get_scope(
145		me: *mut ::std::os::raw::c_void,
146		error_scope: *mut C::ICapeString,
147	) -> CapeResult {
148		let p = me as *mut CapeErrorImpl;
149		if error_scope.is_null() {
150			COBIAERR_NULLPOINTER
151		} else {
152			let mut error_scope=unsafe{*((&error_scope as *const *mut crate::C::ICapeString) as *mut *mut crate::C::ICapeString)};
153			let error_scope=CapeStringOut::new(&mut error_scope);
154			match unsafe { error_scope.set_string(&(*p).scope) } {
155				Ok(_) => COBIAERR_NOERROR,
156				Err(err) => match err {
157					COBIAError::Code(code) => {
158						return code;
159					}
160					_ => {
161						assert!(false);
162						return COBIAERR_UNKNOWNERROR;
163					}
164				},
165			}
166		}
167	}
168
169	const VTABLE: C::ICapeError_VTable = C::ICapeError_VTable {
170		base: C::ICobiaBase_VTable {
171			addReference: Some(CapeErrorImpl::add_reference),
172			release: Some(CapeErrorImpl::release),
173		},
174		getErrorText: Some(
175			CapeErrorImpl::get_error_text
176				as unsafe extern "C" fn(
177					me: *mut ::std::os::raw::c_void,
178					errorText: *mut C::ICapeString,
179				) -> CapeResult,
180		),
181		getCause: Some(
182			CapeErrorImpl::get_cause
183				as unsafe extern "C" fn(
184					me: *mut ::std::os::raw::c_void,
185					cause: *mut *mut C::ICapeError,
186				) -> CapeResult,
187		),
188		getSource: Some(
189			CapeErrorImpl::get_source
190				as unsafe extern "C" fn(
191					me: *mut ::std::os::raw::c_void,
192					componentDescription: *mut C::ICapeString,
193				) -> CapeResult,
194		),
195		getScope: Some(
196			CapeErrorImpl::get_scope
197				as unsafe extern "C" fn(
198					me: *mut ::std::os::raw::c_void,
199					errorScope: *mut C::ICapeString,
200				) -> CapeResult,
201		),
202	};
203}
204
205
206