xref: /openbmc/qemu/rust/qemu-api/src/error.rs (revision b4ff3cf34fa09b28a480870b98377bac183833c8)
1*b4ff3cf3SPaolo Bonzini // SPDX-License-Identifier: GPL-2.0-or-later
2*b4ff3cf3SPaolo Bonzini 
3*b4ff3cf3SPaolo Bonzini //! Error propagation for QEMU Rust code
4*b4ff3cf3SPaolo Bonzini //!
5*b4ff3cf3SPaolo Bonzini //! This module contains [`Error`], the bridge between Rust errors and
6*b4ff3cf3SPaolo Bonzini //! [`Result`](std::result::Result)s and QEMU's C [`Error`](bindings::Error)
7*b4ff3cf3SPaolo Bonzini //! struct.
8*b4ff3cf3SPaolo Bonzini //!
9*b4ff3cf3SPaolo Bonzini //! For FFI code, [`Error`] provides functions to simplify conversion between
10*b4ff3cf3SPaolo Bonzini //! the Rust ([`Result<>`](std::result::Result)) and C (`Error**`) conventions:
11*b4ff3cf3SPaolo Bonzini //!
12*b4ff3cf3SPaolo Bonzini //! * [`ok_or_propagate`](crate::Error::ok_or_propagate),
13*b4ff3cf3SPaolo Bonzini //!   [`bool_or_propagate`](crate::Error::bool_or_propagate),
14*b4ff3cf3SPaolo Bonzini //!   [`ptr_or_propagate`](crate::Error::ptr_or_propagate) can be used to build
15*b4ff3cf3SPaolo Bonzini //!   a C return value while also propagating an error condition
16*b4ff3cf3SPaolo Bonzini //!
17*b4ff3cf3SPaolo Bonzini //! * [`err_or_else`](crate::Error::err_or_else) and
18*b4ff3cf3SPaolo Bonzini //!   [`err_or_unit`](crate::Error::err_or_unit) can be used to build a `Result`
19*b4ff3cf3SPaolo Bonzini //!
20*b4ff3cf3SPaolo Bonzini //! This module is most commonly used at the boundary between C and Rust code;
21*b4ff3cf3SPaolo Bonzini //! other code will usually access it through the
22*b4ff3cf3SPaolo Bonzini //! [`qemu_api::Result`](crate::Result) type alias, and will use the
23*b4ff3cf3SPaolo Bonzini //! [`std::error::Error`] interface to let C errors participate in Rust's error
24*b4ff3cf3SPaolo Bonzini //! handling functionality.
25*b4ff3cf3SPaolo Bonzini //!
26*b4ff3cf3SPaolo Bonzini //! Rust code can also create use this module to create an error object that
27*b4ff3cf3SPaolo Bonzini //! will be passed up to C code, though in most cases this will be done
28*b4ff3cf3SPaolo Bonzini //! transparently through the `?` operator.  Errors can be constructed from a
29*b4ff3cf3SPaolo Bonzini //! simple error string, from an [`anyhow::Error`] to pass any other Rust error
30*b4ff3cf3SPaolo Bonzini //! type up to C code, or from a combination of the two.
31*b4ff3cf3SPaolo Bonzini //!
32*b4ff3cf3SPaolo Bonzini //! The third case, corresponding to [`Error::with_error`], is the only one that
33*b4ff3cf3SPaolo Bonzini //! requires mentioning [`qemu_api::Error`](crate::Error) explicitly.  Similar
34*b4ff3cf3SPaolo Bonzini //! to how QEMU's C code handles errno values, the string and the
35*b4ff3cf3SPaolo Bonzini //! `anyhow::Error` object will be concatenated with `:` as the separator.
36*b4ff3cf3SPaolo Bonzini 
37*b4ff3cf3SPaolo Bonzini use std::{
38*b4ff3cf3SPaolo Bonzini     borrow::Cow,
39*b4ff3cf3SPaolo Bonzini     ffi::{c_char, c_int, c_void, CStr},
40*b4ff3cf3SPaolo Bonzini     fmt::{self, Display},
41*b4ff3cf3SPaolo Bonzini     panic, ptr,
42*b4ff3cf3SPaolo Bonzini };
43*b4ff3cf3SPaolo Bonzini 
44*b4ff3cf3SPaolo Bonzini use foreign::{prelude::*, OwnedPointer};
45*b4ff3cf3SPaolo Bonzini 
46*b4ff3cf3SPaolo Bonzini use crate::bindings;
47*b4ff3cf3SPaolo Bonzini 
48*b4ff3cf3SPaolo Bonzini pub type Result<T> = std::result::Result<T, Error>;
49*b4ff3cf3SPaolo Bonzini 
50*b4ff3cf3SPaolo Bonzini #[derive(Debug)]
51*b4ff3cf3SPaolo Bonzini pub struct Error {
52*b4ff3cf3SPaolo Bonzini     msg: Option<Cow<'static, str>>,
53*b4ff3cf3SPaolo Bonzini     /// Appends the print string of the error to the msg if not None
54*b4ff3cf3SPaolo Bonzini     cause: Option<anyhow::Error>,
55*b4ff3cf3SPaolo Bonzini     file: &'static str,
56*b4ff3cf3SPaolo Bonzini     line: u32,
57*b4ff3cf3SPaolo Bonzini }
58*b4ff3cf3SPaolo Bonzini 
59*b4ff3cf3SPaolo Bonzini impl std::error::Error for Error {
60*b4ff3cf3SPaolo Bonzini     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
61*b4ff3cf3SPaolo Bonzini         self.cause.as_ref().map(AsRef::as_ref)
62*b4ff3cf3SPaolo Bonzini     }
63*b4ff3cf3SPaolo Bonzini 
64*b4ff3cf3SPaolo Bonzini     #[allow(deprecated)]
65*b4ff3cf3SPaolo Bonzini     fn description(&self) -> &str {
66*b4ff3cf3SPaolo Bonzini         self.msg
67*b4ff3cf3SPaolo Bonzini             .as_deref()
68*b4ff3cf3SPaolo Bonzini             .or_else(|| self.cause.as_deref().map(std::error::Error::description))
69*b4ff3cf3SPaolo Bonzini             .expect("no message nor cause?")
70*b4ff3cf3SPaolo Bonzini     }
71*b4ff3cf3SPaolo Bonzini }
72*b4ff3cf3SPaolo Bonzini 
73*b4ff3cf3SPaolo Bonzini impl Display for Error {
74*b4ff3cf3SPaolo Bonzini     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75*b4ff3cf3SPaolo Bonzini         let mut prefix = "";
76*b4ff3cf3SPaolo Bonzini         if let Some(ref msg) = self.msg {
77*b4ff3cf3SPaolo Bonzini             write!(f, "{msg}")?;
78*b4ff3cf3SPaolo Bonzini             prefix = ": ";
79*b4ff3cf3SPaolo Bonzini         }
80*b4ff3cf3SPaolo Bonzini         if let Some(ref cause) = self.cause {
81*b4ff3cf3SPaolo Bonzini             write!(f, "{prefix}{cause}")?;
82*b4ff3cf3SPaolo Bonzini         } else if prefix.is_empty() {
83*b4ff3cf3SPaolo Bonzini             panic!("no message nor cause?");
84*b4ff3cf3SPaolo Bonzini         }
85*b4ff3cf3SPaolo Bonzini         Ok(())
86*b4ff3cf3SPaolo Bonzini     }
87*b4ff3cf3SPaolo Bonzini }
88*b4ff3cf3SPaolo Bonzini 
89*b4ff3cf3SPaolo Bonzini impl From<String> for Error {
90*b4ff3cf3SPaolo Bonzini     #[track_caller]
91*b4ff3cf3SPaolo Bonzini     fn from(msg: String) -> Self {
92*b4ff3cf3SPaolo Bonzini         let location = panic::Location::caller();
93*b4ff3cf3SPaolo Bonzini         Error {
94*b4ff3cf3SPaolo Bonzini             msg: Some(Cow::Owned(msg)),
95*b4ff3cf3SPaolo Bonzini             cause: None,
96*b4ff3cf3SPaolo Bonzini             file: location.file(),
97*b4ff3cf3SPaolo Bonzini             line: location.line(),
98*b4ff3cf3SPaolo Bonzini         }
99*b4ff3cf3SPaolo Bonzini     }
100*b4ff3cf3SPaolo Bonzini }
101*b4ff3cf3SPaolo Bonzini 
102*b4ff3cf3SPaolo Bonzini impl From<&'static str> for Error {
103*b4ff3cf3SPaolo Bonzini     #[track_caller]
104*b4ff3cf3SPaolo Bonzini     fn from(msg: &'static str) -> Self {
105*b4ff3cf3SPaolo Bonzini         let location = panic::Location::caller();
106*b4ff3cf3SPaolo Bonzini         Error {
107*b4ff3cf3SPaolo Bonzini             msg: Some(Cow::Borrowed(msg)),
108*b4ff3cf3SPaolo Bonzini             cause: None,
109*b4ff3cf3SPaolo Bonzini             file: location.file(),
110*b4ff3cf3SPaolo Bonzini             line: location.line(),
111*b4ff3cf3SPaolo Bonzini         }
112*b4ff3cf3SPaolo Bonzini     }
113*b4ff3cf3SPaolo Bonzini }
114*b4ff3cf3SPaolo Bonzini 
115*b4ff3cf3SPaolo Bonzini impl From<anyhow::Error> for Error {
116*b4ff3cf3SPaolo Bonzini     #[track_caller]
117*b4ff3cf3SPaolo Bonzini     fn from(error: anyhow::Error) -> Self {
118*b4ff3cf3SPaolo Bonzini         let location = panic::Location::caller();
119*b4ff3cf3SPaolo Bonzini         Error {
120*b4ff3cf3SPaolo Bonzini             msg: None,
121*b4ff3cf3SPaolo Bonzini             cause: Some(error),
122*b4ff3cf3SPaolo Bonzini             file: location.file(),
123*b4ff3cf3SPaolo Bonzini             line: location.line(),
124*b4ff3cf3SPaolo Bonzini         }
125*b4ff3cf3SPaolo Bonzini     }
126*b4ff3cf3SPaolo Bonzini }
127*b4ff3cf3SPaolo Bonzini 
128*b4ff3cf3SPaolo Bonzini impl Error {
129*b4ff3cf3SPaolo Bonzini     /// Create a new error, prepending `msg` to the
130*b4ff3cf3SPaolo Bonzini     /// description of `cause`
131*b4ff3cf3SPaolo Bonzini     #[track_caller]
132*b4ff3cf3SPaolo Bonzini     pub fn with_error(msg: impl Into<Cow<'static, str>>, cause: impl Into<anyhow::Error>) -> Self {
133*b4ff3cf3SPaolo Bonzini         let location = panic::Location::caller();
134*b4ff3cf3SPaolo Bonzini         Error {
135*b4ff3cf3SPaolo Bonzini             msg: Some(msg.into()),
136*b4ff3cf3SPaolo Bonzini             cause: Some(cause.into()),
137*b4ff3cf3SPaolo Bonzini             file: location.file(),
138*b4ff3cf3SPaolo Bonzini             line: location.line(),
139*b4ff3cf3SPaolo Bonzini         }
140*b4ff3cf3SPaolo Bonzini     }
141*b4ff3cf3SPaolo Bonzini 
142*b4ff3cf3SPaolo Bonzini     /// Consume a result, returning `false` if it is an error and
143*b4ff3cf3SPaolo Bonzini     /// `true` if it is successful.  The error is propagated into
144*b4ff3cf3SPaolo Bonzini     /// `errp` like the C API `error_propagate` would do.
145*b4ff3cf3SPaolo Bonzini     ///
146*b4ff3cf3SPaolo Bonzini     /// # Safety
147*b4ff3cf3SPaolo Bonzini     ///
148*b4ff3cf3SPaolo Bonzini     /// `errp` must be a valid argument to `error_propagate`;
149*b4ff3cf3SPaolo Bonzini     /// typically it is received from C code and need not be
150*b4ff3cf3SPaolo Bonzini     /// checked further at the Rust↔C boundary.
151*b4ff3cf3SPaolo Bonzini     pub unsafe fn bool_or_propagate(result: Result<()>, errp: *mut *mut bindings::Error) -> bool {
152*b4ff3cf3SPaolo Bonzini         // SAFETY: caller guarantees errp is valid
153*b4ff3cf3SPaolo Bonzini         unsafe { Self::ok_or_propagate(result, errp) }.is_some()
154*b4ff3cf3SPaolo Bonzini     }
155*b4ff3cf3SPaolo Bonzini 
156*b4ff3cf3SPaolo Bonzini     /// Consume a result, returning a `NULL` pointer if it is an error and
157*b4ff3cf3SPaolo Bonzini     /// a C representation of the contents if it is successful.  This is
158*b4ff3cf3SPaolo Bonzini     /// similar to the C API `error_propagate`, but it panics if `*errp`
159*b4ff3cf3SPaolo Bonzini     /// is not `NULL`.
160*b4ff3cf3SPaolo Bonzini     ///
161*b4ff3cf3SPaolo Bonzini     /// # Safety
162*b4ff3cf3SPaolo Bonzini     ///
163*b4ff3cf3SPaolo Bonzini     /// `errp` must be a valid argument to `error_propagate`;
164*b4ff3cf3SPaolo Bonzini     /// typically it is received from C code and need not be
165*b4ff3cf3SPaolo Bonzini     /// checked further at the Rust↔C boundary.
166*b4ff3cf3SPaolo Bonzini     ///
167*b4ff3cf3SPaolo Bonzini     /// See [`propagate`](Error::propagate) for more information.
168*b4ff3cf3SPaolo Bonzini     #[must_use]
169*b4ff3cf3SPaolo Bonzini     pub unsafe fn ptr_or_propagate<T: CloneToForeign>(
170*b4ff3cf3SPaolo Bonzini         result: Result<T>,
171*b4ff3cf3SPaolo Bonzini         errp: *mut *mut bindings::Error,
172*b4ff3cf3SPaolo Bonzini     ) -> *mut T::Foreign {
173*b4ff3cf3SPaolo Bonzini         // SAFETY: caller guarantees errp is valid
174*b4ff3cf3SPaolo Bonzini         unsafe { Self::ok_or_propagate(result, errp) }.clone_to_foreign_ptr()
175*b4ff3cf3SPaolo Bonzini     }
176*b4ff3cf3SPaolo Bonzini 
177*b4ff3cf3SPaolo Bonzini     /// Consume a result in the same way as `self.ok()`, but also propagate
178*b4ff3cf3SPaolo Bonzini     /// a possible error into `errp`.  This is similar to the C API
179*b4ff3cf3SPaolo Bonzini     /// `error_propagate`, but it panics if `*errp` is not `NULL`.
180*b4ff3cf3SPaolo Bonzini     ///
181*b4ff3cf3SPaolo Bonzini     /// # Safety
182*b4ff3cf3SPaolo Bonzini     ///
183*b4ff3cf3SPaolo Bonzini     /// `errp` must be a valid argument to `error_propagate`;
184*b4ff3cf3SPaolo Bonzini     /// typically it is received from C code and need not be
185*b4ff3cf3SPaolo Bonzini     /// checked further at the Rust↔C boundary.
186*b4ff3cf3SPaolo Bonzini     ///
187*b4ff3cf3SPaolo Bonzini     /// See [`propagate`](Error::propagate) for more information.
188*b4ff3cf3SPaolo Bonzini     pub unsafe fn ok_or_propagate<T>(
189*b4ff3cf3SPaolo Bonzini         result: Result<T>,
190*b4ff3cf3SPaolo Bonzini         errp: *mut *mut bindings::Error,
191*b4ff3cf3SPaolo Bonzini     ) -> Option<T> {
192*b4ff3cf3SPaolo Bonzini         result.map_err(|err| unsafe { err.propagate(errp) }).ok()
193*b4ff3cf3SPaolo Bonzini     }
194*b4ff3cf3SPaolo Bonzini 
195*b4ff3cf3SPaolo Bonzini     /// Equivalent of the C function `error_propagate`.  Fill `*errp`
196*b4ff3cf3SPaolo Bonzini     /// with the information container in `self` if `errp` is not NULL;
197*b4ff3cf3SPaolo Bonzini     /// then consume it.
198*b4ff3cf3SPaolo Bonzini     ///
199*b4ff3cf3SPaolo Bonzini     /// This is similar to the C API `error_propagate`, but it panics if
200*b4ff3cf3SPaolo Bonzini     /// `*errp` is not `NULL`.
201*b4ff3cf3SPaolo Bonzini     ///
202*b4ff3cf3SPaolo Bonzini     /// # Safety
203*b4ff3cf3SPaolo Bonzini     ///
204*b4ff3cf3SPaolo Bonzini     /// `errp` must be a valid argument to `error_propagate`; it can be
205*b4ff3cf3SPaolo Bonzini     /// `NULL` or it can point to any of:
206*b4ff3cf3SPaolo Bonzini     /// * `error_abort`
207*b4ff3cf3SPaolo Bonzini     /// * `error_fatal`
208*b4ff3cf3SPaolo Bonzini     /// * a local variable of (C) type `Error *`
209*b4ff3cf3SPaolo Bonzini     ///
210*b4ff3cf3SPaolo Bonzini     /// Typically `errp` is received from C code and need not be
211*b4ff3cf3SPaolo Bonzini     /// checked further at the Rust↔C boundary.
212*b4ff3cf3SPaolo Bonzini     pub unsafe fn propagate(self, errp: *mut *mut bindings::Error) {
213*b4ff3cf3SPaolo Bonzini         if errp.is_null() {
214*b4ff3cf3SPaolo Bonzini             return;
215*b4ff3cf3SPaolo Bonzini         }
216*b4ff3cf3SPaolo Bonzini 
217*b4ff3cf3SPaolo Bonzini         // SAFETY: caller guarantees that errp and *errp are valid
218*b4ff3cf3SPaolo Bonzini         unsafe {
219*b4ff3cf3SPaolo Bonzini             assert_eq!(*errp, ptr::null_mut());
220*b4ff3cf3SPaolo Bonzini             bindings::error_propagate(errp, self.clone_to_foreign_ptr());
221*b4ff3cf3SPaolo Bonzini         }
222*b4ff3cf3SPaolo Bonzini     }
223*b4ff3cf3SPaolo Bonzini 
224*b4ff3cf3SPaolo Bonzini     /// Convert a C `Error*` into a Rust `Result`, using
225*b4ff3cf3SPaolo Bonzini     /// `Ok(())` if `c_error` is NULL.  Free the `Error*`.
226*b4ff3cf3SPaolo Bonzini     ///
227*b4ff3cf3SPaolo Bonzini     /// # Safety
228*b4ff3cf3SPaolo Bonzini     ///
229*b4ff3cf3SPaolo Bonzini     /// `c_error` must be `NULL` or valid; typically it was initialized
230*b4ff3cf3SPaolo Bonzini     /// with `ptr::null_mut()` and passed by reference to a C function.
231*b4ff3cf3SPaolo Bonzini     pub unsafe fn err_or_unit(c_error: *mut bindings::Error) -> Result<()> {
232*b4ff3cf3SPaolo Bonzini         // SAFETY: caller guarantees c_error is valid
233*b4ff3cf3SPaolo Bonzini         unsafe { Self::err_or_else(c_error, || ()) }
234*b4ff3cf3SPaolo Bonzini     }
235*b4ff3cf3SPaolo Bonzini 
236*b4ff3cf3SPaolo Bonzini     /// Convert a C `Error*` into a Rust `Result`, calling `f()` to
237*b4ff3cf3SPaolo Bonzini     /// obtain an `Ok` value if `c_error` is NULL.  Free the `Error*`.
238*b4ff3cf3SPaolo Bonzini     ///
239*b4ff3cf3SPaolo Bonzini     /// # Safety
240*b4ff3cf3SPaolo Bonzini     ///
241*b4ff3cf3SPaolo Bonzini     /// `c_error` must be `NULL` or point to a valid C [`struct
242*b4ff3cf3SPaolo Bonzini     /// Error`](bindings::Error); typically it was initialized with
243*b4ff3cf3SPaolo Bonzini     /// `ptr::null_mut()` and passed by reference to a C function.
244*b4ff3cf3SPaolo Bonzini     pub unsafe fn err_or_else<T, F: FnOnce() -> T>(
245*b4ff3cf3SPaolo Bonzini         c_error: *mut bindings::Error,
246*b4ff3cf3SPaolo Bonzini         f: F,
247*b4ff3cf3SPaolo Bonzini     ) -> Result<T> {
248*b4ff3cf3SPaolo Bonzini         // SAFETY: caller guarantees c_error is valid
249*b4ff3cf3SPaolo Bonzini         let err = unsafe { Option::<Self>::from_foreign(c_error) };
250*b4ff3cf3SPaolo Bonzini         match err {
251*b4ff3cf3SPaolo Bonzini             None => Ok(f()),
252*b4ff3cf3SPaolo Bonzini             Some(err) => Err(err),
253*b4ff3cf3SPaolo Bonzini         }
254*b4ff3cf3SPaolo Bonzini     }
255*b4ff3cf3SPaolo Bonzini }
256*b4ff3cf3SPaolo Bonzini 
257*b4ff3cf3SPaolo Bonzini impl FreeForeign for Error {
258*b4ff3cf3SPaolo Bonzini     type Foreign = bindings::Error;
259*b4ff3cf3SPaolo Bonzini 
260*b4ff3cf3SPaolo Bonzini     unsafe fn free_foreign(p: *mut bindings::Error) {
261*b4ff3cf3SPaolo Bonzini         // SAFETY: caller guarantees p is valid
262*b4ff3cf3SPaolo Bonzini         unsafe {
263*b4ff3cf3SPaolo Bonzini             bindings::error_free(p);
264*b4ff3cf3SPaolo Bonzini         }
265*b4ff3cf3SPaolo Bonzini     }
266*b4ff3cf3SPaolo Bonzini }
267*b4ff3cf3SPaolo Bonzini 
268*b4ff3cf3SPaolo Bonzini impl CloneToForeign for Error {
269*b4ff3cf3SPaolo Bonzini     fn clone_to_foreign(&self) -> OwnedPointer<Self> {
270*b4ff3cf3SPaolo Bonzini         // SAFETY: all arguments are controlled by this function
271*b4ff3cf3SPaolo Bonzini         unsafe {
272*b4ff3cf3SPaolo Bonzini             let err: *mut c_void = libc::malloc(std::mem::size_of::<bindings::Error>());
273*b4ff3cf3SPaolo Bonzini             let err: &mut bindings::Error = &mut *err.cast();
274*b4ff3cf3SPaolo Bonzini             *err = bindings::Error {
275*b4ff3cf3SPaolo Bonzini                 msg: format!("{self}").clone_to_foreign_ptr(),
276*b4ff3cf3SPaolo Bonzini                 err_class: bindings::ERROR_CLASS_GENERIC_ERROR,
277*b4ff3cf3SPaolo Bonzini                 src_len: self.file.len() as c_int,
278*b4ff3cf3SPaolo Bonzini                 src: self.file.as_ptr().cast::<c_char>(),
279*b4ff3cf3SPaolo Bonzini                 line: self.line as c_int,
280*b4ff3cf3SPaolo Bonzini                 func: ptr::null_mut(),
281*b4ff3cf3SPaolo Bonzini                 hint: ptr::null_mut(),
282*b4ff3cf3SPaolo Bonzini             };
283*b4ff3cf3SPaolo Bonzini             OwnedPointer::new(err)
284*b4ff3cf3SPaolo Bonzini         }
285*b4ff3cf3SPaolo Bonzini     }
286*b4ff3cf3SPaolo Bonzini }
287*b4ff3cf3SPaolo Bonzini 
288*b4ff3cf3SPaolo Bonzini impl FromForeign for Error {
289*b4ff3cf3SPaolo Bonzini     unsafe fn cloned_from_foreign(c_error: *const bindings::Error) -> Self {
290*b4ff3cf3SPaolo Bonzini         // SAFETY: caller guarantees c_error is valid
291*b4ff3cf3SPaolo Bonzini         unsafe {
292*b4ff3cf3SPaolo Bonzini             let error = &*c_error;
293*b4ff3cf3SPaolo Bonzini             let file = if error.src_len < 0 {
294*b4ff3cf3SPaolo Bonzini                 // NUL-terminated
295*b4ff3cf3SPaolo Bonzini                 CStr::from_ptr(error.src).to_str()
296*b4ff3cf3SPaolo Bonzini             } else {
297*b4ff3cf3SPaolo Bonzini                 // Can become str::from_utf8 with Rust 1.87.0
298*b4ff3cf3SPaolo Bonzini                 std::str::from_utf8(std::slice::from_raw_parts(
299*b4ff3cf3SPaolo Bonzini                     &*error.src.cast::<u8>(),
300*b4ff3cf3SPaolo Bonzini                     error.src_len as usize,
301*b4ff3cf3SPaolo Bonzini                 ))
302*b4ff3cf3SPaolo Bonzini             };
303*b4ff3cf3SPaolo Bonzini 
304*b4ff3cf3SPaolo Bonzini             Error {
305*b4ff3cf3SPaolo Bonzini                 msg: FromForeign::cloned_from_foreign(error.msg),
306*b4ff3cf3SPaolo Bonzini                 cause: None,
307*b4ff3cf3SPaolo Bonzini                 file: file.unwrap(),
308*b4ff3cf3SPaolo Bonzini                 line: error.line as u32,
309*b4ff3cf3SPaolo Bonzini             }
310*b4ff3cf3SPaolo Bonzini         }
311*b4ff3cf3SPaolo Bonzini     }
312*b4ff3cf3SPaolo Bonzini }
313