onepassword_sys/
errors.rs1use byteorder::{BigEndian, ByteOrder};
2
3use crate::buffer::RustBuffer;
4
5pub type FfiResult<T = (), E = Error> = Result<T, E>;
6
7#[derive(Debug)]
8pub enum Error {
9 Error { code: i32, message: String },
10}
11
12impl Error {
13 pub fn code(&self) -> i32 {
14 match self {
15 Self::Error { code, .. } => *code,
16 }
17 }
18}
19
20#[repr(u8)]
21#[expect(dead_code)]
22pub(crate) enum CallStatusCode {
23 Success = 0,
24 Error = 1,
25 Panic = 2,
26}
27
28#[repr(C)]
29pub(crate) struct CallStatus {
30 pub code: CallStatusCode,
31 pub error_buf: RustBuffer,
32}
33
34pub(crate) trait ErrorConverter {
35 type ErrorType;
36
37 fn lift(buf: RustBuffer) -> Self::ErrorType;
38}
39
40pub(crate) struct NoConverter;
41impl ErrorConverter for NoConverter {
42 type ErrorType = std::convert::Infallible;
43
44 fn lift(_buf: RustBuffer) -> Self::ErrorType {
45 panic!("_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None");
46 }
47}
48
49pub(crate) struct StringConverter;
50impl ErrorConverter for StringConverter {
51 type ErrorType = String;
52
53 fn lift(buf: RustBuffer) -> Self::ErrorType {
54 buf.to_string()
55 }
56}
57
58pub(crate) struct ErrorTypeConverter;
59impl ErrorConverter for ErrorTypeConverter {
60 type ErrorType = Error;
61
62 fn lift(buf: RustBuffer) -> Self::ErrorType {
63 let error_variant = BigEndian::read_i32(buf.as_ref());
64 let error_code = BigEndian::read_i32(&buf.as_ref()[4..]);
65
66 match error_variant {
67 1 => {
68 let remainder = &buf.as_ref()[8..];
69 let msg = String::from_utf8_lossy(remainder);
70 Error::Error {
71 code: error_code,
72 message: msg.into_owned(),
73 }
74 }
75 other => unimplemented!("unknown error variant {other}"),
76 }
77 }
78}
79
80pub(crate) fn check_call_status<C: ErrorConverter>(
81 call_status: CallStatus,
82) -> Result<(), C::ErrorType> {
83 match call_status.code {
84 CallStatusCode::Success => Ok(()),
85 CallStatusCode::Error => Err(C::lift(call_status.error_buf)),
86 CallStatusCode::Panic => {
87 let msg = if call_status.error_buf.len > 0 {
88 StringConverter::lift(call_status.error_buf)
89 } else {
90 "Unknown rust panic".to_string()
91 };
92 panic!("{msg}");
93 }
94 }
95}