Fix Rust string parceling

The NDK `writeString` API accepts a UTF-8 string with embedded NULLs,
not just C-style null-terminated strings. This change allows parceling
of Rust strings directly, without requiring conversion to `CString`
first.

Test: atest libbinder_rs-internal_test
Change-Id: I0c5f9a116a17cc3f48622ed3e8f32b8cbe8af891
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index 43850fe..bda538b 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -285,7 +285,6 @@
 fn test_read_write() {
     use crate::binder::Interface;
     use crate::native::Binder;
-    use std::ffi::CString;
 
     let mut service = Binder::new(()).as_binder();
     let mut parcel = Parcel::new_for_test(&mut service).unwrap();
@@ -300,7 +299,7 @@
     assert_eq!(parcel.read::<u64>(), Err(StatusCode::NOT_ENOUGH_DATA));
     assert_eq!(parcel.read::<f32>(), Err(StatusCode::NOT_ENOUGH_DATA));
     assert_eq!(parcel.read::<f64>(), Err(StatusCode::NOT_ENOUGH_DATA));
-    assert_eq!(parcel.read::<Option<CString>>(), Ok(None));
+    assert_eq!(parcel.read::<Option<String>>(), Ok(None));
     assert_eq!(parcel.read::<String>(), Err(StatusCode::UNEXPECTED_NULL));
 
     assert_eq!(parcel.read_binder().err(), Some(StatusCode::BAD_TYPE));
@@ -410,11 +409,24 @@
     }
     assert_eq!(
         parcel.read::<Option<String>>().unwrap().unwrap(),
-        "Hello, Binder!"
+        "Hello, Binder!",
     );
     unsafe {
         assert!(parcel.set_data_position(start).is_ok());
     }
+
+    assert!(parcel.write("Embedded null \0 inside a string").is_ok());
+    unsafe {
+        assert!(parcel.set_data_position(start).is_ok());
+    }
+    assert_eq!(
+        parcel.read::<Option<String>>().unwrap().unwrap(),
+        "Embedded null \0 inside a string",
+    );
+    unsafe {
+        assert!(parcel.set_data_position(start).is_ok());
+    }
+
     assert!(parcel.write(&["str1", "str2", "str3"][..]).is_ok());
     assert!(parcel
         .write(
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 78b3d2c..138b360 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -21,7 +21,8 @@
 use crate::sys;
 
 use std::convert::TryInto;
-use std::ffi::{c_void, CStr, CString};
+use std::ffi::c_void;
+use std::os::raw::c_char;
 use std::ptr;
 
 /// A struct whose instances can be written to a [`Parcel`].
@@ -340,7 +341,7 @@
     }
 }
 
-impl SerializeOption for CStr {
+impl SerializeOption for str {
     fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
         match this {
             None => unsafe {
@@ -356,14 +357,17 @@
             },
             Some(s) => unsafe {
                 // Safety: `Parcel` always contains a valid pointer to an
-                // `AParcel`. `AParcel_writeString` assumes that we pass a
-                // null-terminated C string pointer with no nulls in the middle
-                // of the string. Rust guarantees exactly that for a valid CStr
-                // instance.
+                // `AParcel`. `AParcel_writeString` assumes that we pass a utf-8
+                // string pointer of `length` bytes, which is what str in Rust
+                // is. The docstring for `AParcel_writeString` says that the
+                // string input should be null-terminated, but it doesn't
+                // actually rely on that fact in the code. If this ever becomes
+                // necessary, we will need to null-terminate the str buffer
+                // before sending it.
                 status_result(sys::AParcel_writeString(
                     parcel.as_native_mut(),
-                    s.as_ptr(),
-                    s.to_bytes()
+                    s.as_ptr() as *const c_char,
+                    s.as_bytes()
                         .len()
                         .try_into()
                         .or(Err(StatusCode::BAD_VALUE))?,
@@ -373,29 +377,15 @@
     }
 }
 
-impl SerializeArray for Option<&CStr> {}
+impl SerializeArray for Option<&str> {}
 
-impl Serialize for CStr {
+impl Serialize for str {
     fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
         Some(self).serialize(parcel)
     }
 }
 
-impl Serialize for CString {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
-        Some(self.as_c_str()).serialize(parcel)
-    }
-}
-
-impl SerializeArray for CString {}
-
-impl SerializeOption for CString {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
-        SerializeOption::serialize_option(this.map(CString::as_c_str), parcel)
-    }
-}
-
-impl SerializeArray for Option<CString> {}
+impl SerializeArray for &str {}
 
 impl Serialize for String {
     fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
@@ -413,7 +403,7 @@
 
 impl SerializeArray for Option<String> {}
 
-impl Deserialize for Option<CString> {
+impl Deserialize for Option<String> {
     fn deserialize(parcel: &Parcel) -> Result<Self> {
         let mut vec: Option<Vec<u8>> = None;
         let status = unsafe {
@@ -430,26 +420,15 @@
 
         status_result(status)?;
         vec.map(|mut s| {
-            // The vector includes a null-terminator and CString::new requires
-            // no nulls, including terminating.
+            // The vector includes a null-terminator and we don't want the
+            // string to be null-terminated for Rust.
             s.pop();
-            CString::new(s).or(Err(StatusCode::BAD_VALUE))
+            String::from_utf8(s).or(Err(StatusCode::BAD_VALUE))
         })
         .transpose()
     }
 }
 
-impl DeserializeArray for Option<CString> {}
-
-impl DeserializeOption for String {
-    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
-        let c_str = <Option<CString>>::deserialize(parcel)?;
-        c_str
-            .map(|s| s.into_string().or(Err(StatusCode::BAD_VALUE)))
-            .transpose()
-    }
-}
-
 impl DeserializeArray for Option<String> {}
 
 impl Deserialize for String {
@@ -462,28 +441,6 @@
 
 impl DeserializeArray for String {}
 
-impl SerializeOption for str {
-    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
-        match this {
-            None => parcel.write(&-1i32),
-            Some(s) => {
-                let c_str = CString::new(s).or(Err(StatusCode::BAD_VALUE))?;
-                parcel.write(&c_str)
-            }
-        }
-    }
-}
-
-impl Serialize for str {
-    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
-        Some(self).serialize(parcel)
-    }
-}
-
-impl SerializeArray for &str {}
-
-impl SerializeArray for Option<&str> {}
-
 impl<T: SerializeArray> Serialize for [T] {
     fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
         SerializeArray::serialize_array(self, parcel)
@@ -905,8 +862,9 @@
     let s1 = "Hello, Binder!";
     let s2 = "This is a utf8 string.";
     let s3 = "Some more text here.";
+    let s4 = "Embedded nulls \0 \0";
 
-    let strs = [s1, s2, s3];
+    let strs = [s1, s2, s3, s4];
 
     unsafe {
         assert!(parcel.set_data_position(start).is_ok());