Move SysPropError to rustutils library.
This was being duplicated in every generated Rust system property
library, which meant that they were different types.
Also added `Error` implementation, and moved PropertyWatcherError to
submodule.
Bug: 270547306
Test: Built libplatformproperties_rust
Change-Id: Ib3698b531cdad49e94fa69a75f3677ad9c221c00
diff --git a/system_properties.rs b/system_properties.rs
index a2c869d..f800ccd 100644
--- a/system_properties.rs
+++ b/system_properties.rs
@@ -15,56 +15,22 @@
//! This crate provides the PropertyWatcher type, which watches for changes
//! in Android system properties.
+// Temporary public re-export to avoid breaking dependents.
+pub use self::error::{PropertyWatcherError, Result};
use anyhow::Context;
use libc::timespec;
use std::os::raw::c_char;
use std::ptr::null;
use std::{
ffi::{c_uint, c_void, CStr, CString},
- str::Utf8Error,
time::{Duration, Instant},
};
use system_properties_bindgen::prop_info as PropInfo;
-use thiserror::Error;
+pub mod error;
#[doc(hidden)]
pub mod parsers_formatters;
-/// Errors this crate can generate
-#[derive(Error, Debug)]
-pub enum PropertyWatcherError {
- /// We can't watch for a property whose name contains a NUL character.
- #[error("Cannot convert name to C string")]
- BadNameError(#[from] std::ffi::NulError),
- /// We can only watch for properties that exist when the watcher is created.
- #[error("System property is absent")]
- SystemPropertyAbsent,
- /// System properties are not initialized
- #[error("System properties are not initialized.")]
- Uninitialized,
- /// __system_property_wait timed out.
- #[error("Wait failed")]
- WaitFailed,
- /// read callback was not called
- #[error("__system_property_read_callback did not call callback")]
- ReadCallbackNotCalled,
- /// read callback gave us a NULL pointer
- #[error("__system_property_read_callback gave us a NULL pointer instead of a string")]
- MissingCString,
- /// read callback gave us a bad C string
- #[error("__system_property_read_callback gave us a non-UTF8 C string")]
- BadCString(#[from] Utf8Error),
- /// read callback returned an error
- #[error("Callback failed")]
- CallbackError(#[from] anyhow::Error),
- /// Failure in setting the system property
- #[error("__system_property_set failed.")]
- SetPropertyFailed,
-}
-
-/// Result type specific for this crate.
-pub type Result<T> = std::result::Result<T, PropertyWatcherError>;
-
/// PropertyWatcher takes the name of an Android system property such
/// as `keystore.boot_level`; it can report the current value of this
/// property, or wait for it to change.
@@ -77,11 +43,7 @@
impl PropertyWatcher {
/// Create a PropertyWatcher for the named system property.
pub fn new(name: &str) -> Result<Self> {
- Ok(Self {
- prop_name: CString::new(name)?,
- prop_info: null(),
- serial: 0,
- })
+ Ok(Self { prop_name: CString::new(name)?, prop_info: null(), serial: 0 })
}
// Lazy-initializing accessor for self.prop_info.
@@ -150,17 +112,13 @@
where
F: FnMut(&str, &str) -> anyhow::Result<T>,
{
- let prop_info = self
- .get_prop_info()
- .ok_or(PropertyWatcherError::SystemPropertyAbsent)?;
+ let prop_info = self.get_prop_info().ok_or(PropertyWatcherError::SystemPropertyAbsent)?;
let mut result = Err(PropertyWatcherError::ReadCallbackNotCalled);
Self::read_raw(prop_info, |name, value| {
// use a wrapping closure as an erzatz try block.
result = (|| {
let name = name.ok_or(PropertyWatcherError::MissingCString)?.to_str()?;
- let value = value
- .ok_or(PropertyWatcherError::MissingCString)?
- .to_str()?;
+ let value = value.ok_or(PropertyWatcherError::MissingCString)?.to_str()?;
f(name, value).map_err(PropertyWatcherError::CallbackError)
})()
});
@@ -280,11 +238,7 @@
/// Returns `None` if `None` is passed in, or `Some(0)` if `until` is in the past.
fn remaining_time_until(until: Option<Instant>) -> Option<timespec> {
until.map(|until| {
- duration_to_timespec(
- until
- .checked_duration_since(Instant::now())
- .unwrap_or_default(),
- )
+ duration_to_timespec(until.checked_duration_since(Instant::now()).unwrap_or_default())
})
}
@@ -299,10 +253,7 @@
/// Returns true if the system property `name` has the value "1", "y", "yes", "on", or "true",
/// false for "0", "n", "no", "off", or "false", or `default_value` otherwise.
pub fn read_bool(name: &str, default_value: bool) -> Result<bool> {
- Ok(read(name)?
- .as_deref()
- .and_then(parse_bool)
- .unwrap_or(default_value))
+ Ok(read(name)?.as_deref().and_then(parse_bool).unwrap_or(default_value))
}
/// Writes a system property.
@@ -312,12 +263,8 @@
unsafe {
// If successful, __system_property_set returns 0, otherwise, returns -1.
system_properties_bindgen::__system_property_set(
- CString::new(name)
- .context("Failed to construct CString from name.")?
- .as_ptr(),
- CString::new(value)
- .context("Failed to construct CString from value.")?
- .as_ptr(),
+ CString::new(name).context("Failed to construct CString from name.")?.as_ptr(),
+ CString::new(value).context("Failed to construct CString from value.")?.as_ptr(),
)
} == 0
{
diff --git a/system_properties/error.rs b/system_properties/error.rs
new file mode 100644
index 0000000..df0cca8
--- /dev/null
+++ b/system_properties/error.rs
@@ -0,0 +1,67 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Errors accessing system properties.
+
+use std::str::Utf8Error;
+use thiserror::Error;
+
+/// Errors this crate can generate
+#[derive(Debug, Error)]
+pub enum PropertyWatcherError {
+ /// We can't watch for a property whose name contains a NUL character.
+ #[error("Cannot convert name to C string")]
+ BadNameError(#[from] std::ffi::NulError),
+ /// We can only watch for properties that exist when the watcher is created.
+ #[error("System property is absent")]
+ SystemPropertyAbsent,
+ /// System properties are not initialized
+ #[error("System properties are not initialized.")]
+ Uninitialized,
+ /// __system_property_wait timed out.
+ #[error("Wait failed")]
+ WaitFailed,
+ /// read callback was not called
+ #[error("__system_property_read_callback did not call callback")]
+ ReadCallbackNotCalled,
+ /// read callback gave us a NULL pointer
+ #[error("__system_property_read_callback gave us a NULL pointer instead of a string")]
+ MissingCString,
+ /// read callback gave us a bad C string
+ #[error("__system_property_read_callback gave us a non-UTF8 C string")]
+ BadCString(#[from] Utf8Error),
+ /// read callback returned an error
+ #[error("Callback failed")]
+ CallbackError(#[from] anyhow::Error),
+ /// Failure in setting the system property
+ #[error("__system_property_set failed.")]
+ SetPropertyFailed,
+}
+
+/// Result type specific for this crate.
+pub type Result<T> = std::result::Result<T, PropertyWatcherError>;
+
+/// Errors returned by generated system property accessors.
+#[derive(Debug, Error)]
+pub enum SysPropError {
+ /// Failed to fetch the system property.
+ #[error("Failed to fetch system property: {0}")]
+ FetchError(PropertyWatcherError),
+ /// Failed to set the system property.
+ #[error("Failed to set system property: {0}")]
+ SetError(PropertyWatcherError),
+ /// Failed to parse the system property value.
+ #[error("Failed to parse the system property value: {0}")]
+ ParseError(String),
+}