1 //! Library for interacting with aconfigd. 2 use crate::ffi::{CppAconfigd, CppResultStatus, CppStringResult, CppVoidResult}; 3 use cxx::{let_cxx_string, CxxString, UniquePtr}; 4 use std::error::Error; 5 use std::fmt; 6 7 /// Wrapper for interacting with aconfigd. 8 pub struct Aconfigd { 9 cpp_aconfigd: UniquePtr<CppAconfigd>, 10 } 11 12 impl Aconfigd { 13 /// Create a new Aconfigd. new(root_dir: &str, persist_storage_records: &str) -> Self14 pub fn new(root_dir: &str, persist_storage_records: &str) -> Self { 15 let_cxx_string!(root_dir_ = root_dir); 16 let_cxx_string!(persist_storage_records_ = persist_storage_records); 17 Self { cpp_aconfigd: ffi::new_cpp_aconfigd(&root_dir_, &persist_storage_records_) } 18 } 19 20 /// Create persistent storage files for platform partition. initialize_platform_storage(&self) -> Result<(), CppAconfigdError>21 pub fn initialize_platform_storage(&self) -> Result<(), CppAconfigdError> { 22 self.cpp_aconfigd.initialize_platform_storage().into() 23 } 24 25 /// Create persistent storage files for mainline modules. initialize_mainline_storage(&self) -> Result<(), CppAconfigdError>26 pub fn initialize_mainline_storage(&self) -> Result<(), CppAconfigdError> { 27 self.cpp_aconfigd.initialize_mainline_storage().into() 28 } 29 30 /// Read storage records into memory. initialize_in_memory_storage_records(&self) -> Result<(), CppAconfigdError>31 pub fn initialize_in_memory_storage_records(&self) -> Result<(), CppAconfigdError> { 32 self.cpp_aconfigd.initialize_in_memory_storage_records().into() 33 } 34 35 /// Process a `StorageRequestMessages`, and return the bytes of a `StorageReturnMessages`. 36 /// 37 /// `messages_bytes` should contain the serialized bytes of a `StorageRequestMessages`. handle_socket_request( &self, messages_bytes: &[u8], ) -> Result<Vec<u8>, CppAconfigdError>38 pub fn handle_socket_request( 39 &self, 40 messages_bytes: &[u8], 41 ) -> Result<Vec<u8>, CppAconfigdError> { 42 let_cxx_string!(messages_string_ = messages_bytes); 43 let res: Result<UniquePtr<CxxString>, CppAconfigdError> = 44 self.cpp_aconfigd.handle_socket_request(&messages_string_).into(); 45 res.map(|s| s.as_bytes().to_vec()) 46 } 47 } 48 49 /// Represents an error in the C++ aconfigd. 50 /// 51 /// The C++ aconfigd uses the C++ Result type. Result errors are mapped 52 /// to this type. 53 #[derive(Debug)] 54 pub struct CppAconfigdError { 55 msg: String, 56 } 57 58 impl CppAconfigdError { new(msg: &str) -> Self59 pub fn new(msg: &str) -> Self { 60 Self { msg: msg.to_string() } 61 } 62 } 63 64 impl fmt::Display for CppAconfigdError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 66 write!(f, "CppAconfigd error: {}", self.msg) 67 } 68 } 69 70 impl Error for CppAconfigdError {} 71 72 #[cxx::bridge(namespace = "aconfigdwrapper")] 73 mod ffi { 74 enum CppResultStatus { 75 Ok, 76 Err, 77 } 78 79 struct CppVoidResult { 80 error_message: String, 81 status: CppResultStatus, 82 } 83 84 struct CppStringResult { 85 data: UniquePtr<CxxString>, 86 error_message: String, 87 status: CppResultStatus, 88 } 89 90 unsafe extern "C++" { 91 include!("libcxx_aconfigd.hpp"); 92 93 type CppAconfigd; 94 new_cpp_aconfigd(str1: &CxxString, str2: &CxxString) -> UniquePtr<CppAconfigd>95 fn new_cpp_aconfigd(str1: &CxxString, str2: &CxxString) -> UniquePtr<CppAconfigd>; initialize_platform_storage(&self) -> CppVoidResult96 fn initialize_platform_storage(&self) -> CppVoidResult; initialize_mainline_storage(&self) -> CppVoidResult97 fn initialize_mainline_storage(&self) -> CppVoidResult; 98 initialize_in_memory_storage_records(&self) -> CppVoidResult99 fn initialize_in_memory_storage_records(&self) -> CppVoidResult; handle_socket_request(&self, message_string: &CxxString) -> CppStringResult100 fn handle_socket_request(&self, message_string: &CxxString) -> CppStringResult; 101 } 102 } 103 104 impl Into<Result<(), CppAconfigdError>> for CppVoidResult { into(self) -> Result<(), CppAconfigdError>105 fn into(self) -> Result<(), CppAconfigdError> { 106 match self.status { 107 CppResultStatus::Ok => Ok(()), 108 CppResultStatus::Err => Err(CppAconfigdError::new(&self.error_message)), 109 _ => Err(CppAconfigdError::new("unknown status")), 110 } 111 } 112 } 113 114 impl Into<Result<UniquePtr<CxxString>, CppAconfigdError>> for CppStringResult { into(self) -> Result<UniquePtr<CxxString>, CppAconfigdError>115 fn into(self) -> Result<UniquePtr<CxxString>, CppAconfigdError> { 116 match self.status { 117 CppResultStatus::Ok => Ok(self.data), 118 CppResultStatus::Err => Err(CppAconfigdError::new(&self.error_message)), 119 _ => Err(CppAconfigdError::new("unknown status")), 120 } 121 } 122 } 123