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),
+}