bitwarden_uniffi_error/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::sync::OnceLock;
4
5#[allow(clippy::type_complexity)]
6static ERROR_TO_UNIFFI_ERROR: OnceLock<
7    Box<dyn Fn(Box<dyn std::error::Error + Send + Sync>) -> anyhow::Error + Send + Sync + 'static>,
8> = OnceLock::new();
9
10pub use anyhow::Error;
11
12/// Configure an error converter to convert errors in calls to
13/// [`uniffi::custom_type!`](https://docs.rs/uniffi/latest/uniffi/macro.custom_type.html) into the
14/// main error of the application (`bitwarden_uniffi::error::BitwardenError). This is needed because
15/// if the errors don't match, Uniffi will panic instead of returning an error. This needs to be
16/// called by the `bitwarden_uniffi` crate before any other Uniffi code is run.
17pub fn set_error_to_uniffi_error<F>(f: F)
18where
19    F: Fn(Box<dyn std::error::Error + Send + Sync>) -> anyhow::Error + Send + Sync + 'static,
20{
21    let _ = ERROR_TO_UNIFFI_ERROR.set(Box::new(f));
22}
23
24fn convert_error<E: std::error::Error + Send + Sync + 'static>(error: E) -> anyhow::Error {
25    if let Some(f) = ERROR_TO_UNIFFI_ERROR.get() {
26        f(Box::new(error))
27    } else {
28        anyhow::Error::new(error)
29    }
30}
31
32/// Convert a `Result` into one that will not cause a panic when called inside
33/// [`uniffi::custom_type!`](https://docs.rs/uniffi/latest/uniffi/macro.custom_type.html). It is
34/// required that all the results created inside a `custom_type!` are converted using this function.
35pub fn convert_result<T, E: std::error::Error + Send + Sync + 'static>(
36    result: Result<T, E>,
37) -> Result<T, anyhow::Error> {
38    result.map_err(|e| convert_error(e))
39}