Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5afb34b2 authored by Andrew Walbran's avatar Andrew Walbran
Browse files

Add methods to construct errors from Rust strings.

This is more convenient in most cases than a CStr, and will let callers
stop duplicating the code to convert it.

Bug: 234019127
Test: atest compos_key_tests MicrodroidHostTestCases MicrodroidTestApp libbinder_rs-internal_test
Change-Id: Idc6684f22f33d4ff79d2326499d089dc85e213ea
parent 7c1c124b
Loading
Loading
Loading
Loading
+56 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ use crate::binder::AsNative;
use crate::sys;

use std::error;
use std::ffi::CStr;
use std::ffi::{CStr, CString};
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::result;

@@ -104,6 +104,10 @@ unsafe impl Sync for Status {}
// A thread-local `AStatus` would not be valid.
unsafe impl Send for Status {}

fn to_cstring<T: AsRef<str>>(message: T) -> Option<CString> {
    CString::new(message.as_ref()).ok()
}

impl Status {
    /// Create a status object representing a successful transaction.
    pub fn ok() -> Self {
@@ -146,6 +150,11 @@ impl Status {
        Self(ptr)
    }

    /// Creates a status object from a service specific error.
    pub fn new_service_specific_error_str<T: AsRef<str>>(err: i32, message: Option<T>) -> Status {
        Self::new_service_specific_error(err, message.and_then(to_cstring).as_deref())
    }

    /// Create a status object from an exception code
    pub fn new_exception(exception: ExceptionCode, message: Option<&CStr>) -> Status {
        if let Some(message) = message {
@@ -158,6 +167,14 @@ impl Status {
        }
    }

    /// Creates a status object from an exception code and message.
    pub fn new_exception_str<T: AsRef<str>>(
        exception: ExceptionCode,
        message: Option<T>,
    ) -> Status {
        Self::new_exception(exception, message.and_then(to_cstring).as_deref())
    }

    /// Create a status object from a raw `AStatus` pointer.
    ///
    /// # Safety
@@ -371,3 +388,41 @@ unsafe impl AsNative<sys::AStatus> for Status {
        self.0
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn make_service_specific_error() {
        let status = Status::new_service_specific_error_str(-42, Some("message"));

        assert!(!status.is_ok());
        assert_eq!(status.exception_code(), ExceptionCode::SERVICE_SPECIFIC);
        assert_eq!(status.service_specific_error(), -42);
        assert_eq!(
            status.get_description(),
            "Status(-8, EX_SERVICE_SPECIFIC): '-42: message'".to_string()
        );
    }

    #[test]
    fn make_exception() {
        let status = Status::new_exception_str(ExceptionCode::ILLEGAL_STATE, Some("message"));

        assert!(!status.is_ok());
        assert_eq!(status.exception_code(), ExceptionCode::ILLEGAL_STATE);
        assert_eq!(status.service_specific_error(), 0);
        assert_eq!(status.get_description(), "Status(-5, EX_ILLEGAL_STATE): 'message'".to_string());
    }

    #[test]
    fn make_exception_null() {
        let status = Status::new_exception_str(ExceptionCode::ILLEGAL_STATE, Some("one\0two"));

        assert!(!status.is_ok());
        assert_eq!(status.exception_code(), ExceptionCode::ILLEGAL_STATE);
        assert_eq!(status.service_specific_error(), 0);
        assert_eq!(status.get_description(), "Status(-5, EX_ILLEGAL_STATE): ''".to_string());
    }
}