descriptor_reflection: Dedupe cross platform

descriptor_reflection.rs is the exact same on both windows and unix, so
moved it to the outer module in base

Test: built and presubmit
Bug: 215619368
Change-Id: I346fa58e651953e2a77b806fa7456af2c1b02cb9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3555732
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Richard Zhang <rizhang@google.com>
diff --git a/base/src/windows/descriptor_reflection.rs b/base/src/descriptor_reflection.rs
similarity index 99%
rename from base/src/windows/descriptor_reflection.rs
rename to base/src/descriptor_reflection.rs
index bf7cff1..d75d988 100644
--- a/base/src/windows/descriptor_reflection.rs
+++ b/base/src/descriptor_reflection.rs
@@ -1,4 +1,4 @@
-// Copyright 2022 The Chromium OS Authors. All rights reserved.
+// Copyright 2020 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/base/src/lib.rs b/base/src/lib.rs
index f25a964..45c72d8 100644
--- a/base/src/lib.rs
+++ b/base/src/lib.rs
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 pub mod common;
+pub mod descriptor_reflection;
 
 #[cfg(unix)]
 pub mod unix;
diff --git a/base/src/unix/descriptor_reflection.rs b/base/src/unix/descriptor_reflection.rs
deleted file mode 100644
index f05f541..0000000
--- a/base/src/unix/descriptor_reflection.rs
+++ /dev/null
@@ -1,543 +0,0 @@
-// Copyright 2020 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//! Provides infrastructure for de/serializing descriptors embedded in Rust data structures.
-//!
-//! # Example
-//!
-//! ```
-//! use serde_json::to_string;
-//! use crate::platform::{
-//!     FileSerdeWrapper, FromRawDescriptor, SafeDescriptor, SerializeDescriptors,
-//!     deserialize_with_descriptors,
-//! };
-//! use tempfile::tempfile;
-//!
-//! let tmp_f = tempfile().unwrap();
-//!
-//! // Uses a simple wrapper to serialize a File because we can't implement Serialize for File.
-//! let data = FileSerdeWrapper(tmp_f);
-//!
-//! // Wraps Serialize types to collect side channel descriptors as Serialize is called.
-//! let data_wrapper = SerializeDescriptors::new(&data);
-//!
-//! // Use the wrapper with any serializer to serialize data is normal, grabbing descriptors
-//! // as the data structures are serialized by the serializer.
-//! let out_json = serde_json::to_string(&data_wrapper).expect("failed to serialize");
-//!
-//! // If data_wrapper contains any side channel descriptor refs
-//! // (it contains tmp_f in this case), we can retrieve the actual descriptors
-//! // from the side channel using into_descriptors().
-//! let out_descriptors = data_wrapper.into_descriptors();
-//!
-//! // When sending out_json over some transport, also send out_descriptors.
-//!
-//! // For this example, we aren't really transporting data across the process, but we do need to
-//! // convert the descriptor type.
-//! let mut safe_descriptors = out_descriptors
-//!     .iter()
-//!     .map(|&v| Some(unsafe { SafeDescriptor::from_raw_descriptor(v) }))
-//!     .collect();
-//! std::mem::forget(data); // Prevent double drop of tmp_f.
-//!
-//! // The deserialize_with_descriptors function is used give the descriptor deserializers access
-//! // to side channel descriptors.
-//! let res: FileSerdeWrapper =
-//!     deserialize_with_descriptors(|| serde_json::from_str(&out_json), &mut safe_descriptors)
-//!        .expect("failed to deserialize");
-//! ```
-
-use std::{
-    cell::{Cell, RefCell},
-    convert::TryInto,
-    fmt,
-    fs::File,
-    ops::{Deref, DerefMut},
-    panic::{catch_unwind, resume_unwind, AssertUnwindSafe},
-};
-
-use serde::{
-    de::{
-        Error, Visitor, {self},
-    },
-    ser, Deserialize, Deserializer, Serialize, Serializer,
-};
-
-use super::{RawDescriptor, SafeDescriptor};
-
-thread_local! {
-    static DESCRIPTOR_DST: RefCell<Option<Vec<RawDescriptor>>> = Default::default();
-}
-
-/// Initializes the thread local storage for descriptor serialization. Fails if it was already
-/// initialized without an intervening `take_descriptor_dst` on this thread.
-fn init_descriptor_dst() -> Result<(), &'static str> {
-    DESCRIPTOR_DST.with(|d| {
-        let mut descriptors = d.borrow_mut();
-        if descriptors.is_some() {
-            return Err(
-                "attempt to initialize descriptor destination that was already initialized",
-            );
-        }
-        *descriptors = Some(Default::default());
-        Ok(())
-    })
-}
-
-/// Takes the thread local storage for descriptor serialization. Fails if there wasn't a prior call
-/// to `init_descriptor_dst` on this thread.
-fn take_descriptor_dst() -> Result<Vec<RawDescriptor>, &'static str> {
-    match DESCRIPTOR_DST.with(|d| d.replace(None)) {
-        Some(d) => Ok(d),
-        None => Err("attempt to take descriptor destination before it was initialized"),
-    }
-}
-
-/// Pushes a descriptor on the thread local destination of descriptors, returning the index in which
-/// the descriptor was pushed.
-//
-/// Returns Err if the thread local destination was not already initialized.
-fn push_descriptor(rd: RawDescriptor) -> Result<usize, &'static str> {
-    DESCRIPTOR_DST.with(|d| {
-        d.borrow_mut()
-            .as_mut()
-            .ok_or("attempt to serialize descriptor without descriptor destination")
-            .map(|descriptors| {
-                let index = descriptors.len();
-                descriptors.push(rd);
-                index
-            })
-    })
-}
-
-/// Serializes a descriptor for later retrieval in a parent `SerializeDescriptors` struct.
-///
-/// If there is no parent `SerializeDescriptors` being serialized, this will return an error.
-///
-/// For convenience, it is recommended to use the `with_raw_descriptor` module in a `#[serde(with =
-/// "...")]` attribute which will make use of this function.
-pub fn serialize_descriptor<S: Serializer>(
-    rd: &RawDescriptor,
-    se: S,
-) -> std::result::Result<S::Ok, S::Error> {
-    let index = push_descriptor(*rd).map_err(ser::Error::custom)?;
-    se.serialize_u32(
-        index
-            .try_into()
-            .map_err(|_| ser::Error::custom("attempt to serialize too many descriptors at once"))?,
-    )
-}
-
-/// Wrapper for a `Serialize` value which will capture any descriptors exported by the value when
-/// given to an ordinary `Serializer`.
-///
-/// This is the corresponding type to use for serialization before using
-/// `deserialize_with_descriptors`.
-///
-/// # Examples
-///
-/// ```
-/// use serde_json::to_string;
-/// use crate::platform::{FileSerdeWrapper, SerializeDescriptors};
-/// use tempfile::tempfile;
-///
-/// let tmp_f = tempfile().unwrap();
-/// let data = FileSerdeWrapper(tmp_f);
-/// let data_wrapper = SerializeDescriptors::new(&data);
-///
-/// // Serializes `v` as normal...
-/// let out_json = serde_json::to_string(&data_wrapper).expect("failed to serialize");
-/// // If `serialize_descriptor` was called, we can capture the descriptors from here.
-/// let out_descriptors = data_wrapper.into_descriptors();
-/// ```
-pub struct SerializeDescriptors<'a, T: Serialize>(&'a T, Cell<Vec<RawDescriptor>>);
-
-impl<'a, T: Serialize> SerializeDescriptors<'a, T> {
-    pub fn new(inner: &'a T) -> Self {
-        Self(inner, Default::default())
-    }
-
-    pub fn into_descriptors(self) -> Vec<RawDescriptor> {
-        self.1.into_inner()
-    }
-}
-
-impl<'a, T: Serialize> Serialize for SerializeDescriptors<'a, T> {
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        init_descriptor_dst().map_err(ser::Error::custom)?;
-
-        // catch_unwind is used to ensure that init_descriptor_dst is always balanced with a call to
-        // take_descriptor_dst afterwards.
-        let res = catch_unwind(AssertUnwindSafe(|| self.0.serialize(serializer)));
-        self.1.set(take_descriptor_dst().unwrap());
-        match res {
-            Ok(r) => r,
-            Err(e) => resume_unwind(e),
-        }
-    }
-}
-
-thread_local! {
-    static DESCRIPTOR_SRC: RefCell<Option<Vec<Option<SafeDescriptor>>>> = Default::default();
-}
-
-/// Sets the thread local storage of descriptors for deserialization. Fails if this was already
-/// called without a call to `take_descriptor_src` on this thread.
-///
-/// This is given as a collection of `Option` so that unused descriptors can be returned.
-fn set_descriptor_src(descriptors: Vec<Option<SafeDescriptor>>) -> Result<(), &'static str> {
-    DESCRIPTOR_SRC.with(|d| {
-        let mut src = d.borrow_mut();
-        if src.is_some() {
-            return Err("attempt to set descriptor source that was already set");
-        }
-        *src = Some(descriptors);
-        Ok(())
-    })
-}
-
-/// Takes the thread local storage of descriptors for deserialization. Fails if the storage was
-/// already taken or never set with `set_descriptor_src`.
-///
-/// If deserialization was done, the descriptors will mostly come back as `None` unless some of them
-/// were unused.
-fn take_descriptor_src() -> Result<Vec<Option<SafeDescriptor>>, &'static str> {
-    DESCRIPTOR_SRC.with(|d| {
-        d.replace(None)
-            .ok_or("attempt to take descriptor source which was never set")
-    })
-}
-
-/// Takes a descriptor at the given index from the thread local source of descriptors.
-//
-/// Returns None if the thread local source was not already initialized.
-fn take_descriptor(index: usize) -> Result<SafeDescriptor, &'static str> {
-    DESCRIPTOR_SRC.with(|d| {
-        d.borrow_mut()
-            .as_mut()
-            .ok_or("attempt to deserialize descriptor without descriptor source")?
-            .get_mut(index)
-            .ok_or("attempt to deserialize out of bounds descriptor")?
-            .take()
-            .ok_or("attempt to deserialize descriptor that was already taken")
-    })
-}
-
-/// Deserializes a descriptor provided via `deserialize_with_descriptors`.
-///
-/// If `deserialize_with_descriptors` is not in the call chain, this will return an error.
-///
-/// For convenience, it is recommended to use the `with_raw_descriptor` module in a `#[serde(with =
-/// "...")]` attribute which will make use of this function.
-pub fn deserialize_descriptor<'de, D>(de: D) -> std::result::Result<SafeDescriptor, D::Error>
-where
-    D: Deserializer<'de>,
-{
-    struct DescriptorVisitor;
-
-    impl<'de> Visitor<'de> for DescriptorVisitor {
-        type Value = u32;
-
-        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-            formatter.write_str("an integer which fits into a u32")
-        }
-
-        fn visit_u8<E: de::Error>(self, value: u8) -> Result<Self::Value, E> {
-            Ok(value as _)
-        }
-
-        fn visit_u16<E: de::Error>(self, value: u16) -> Result<Self::Value, E> {
-            Ok(value as _)
-        }
-
-        fn visit_u32<E: de::Error>(self, value: u32) -> Result<Self::Value, E> {
-            Ok(value)
-        }
-
-        fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
-            value.try_into().map_err(E::custom)
-        }
-
-        fn visit_u128<E: de::Error>(self, value: u128) -> Result<Self::Value, E> {
-            value.try_into().map_err(E::custom)
-        }
-
-        fn visit_i8<E: de::Error>(self, value: i8) -> Result<Self::Value, E> {
-            value.try_into().map_err(E::custom)
-        }
-
-        fn visit_i16<E: de::Error>(self, value: i16) -> Result<Self::Value, E> {
-            value.try_into().map_err(E::custom)
-        }
-
-        fn visit_i32<E: de::Error>(self, value: i32) -> Result<Self::Value, E> {
-            value.try_into().map_err(E::custom)
-        }
-
-        fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
-            value.try_into().map_err(E::custom)
-        }
-
-        fn visit_i128<E: de::Error>(self, value: i128) -> Result<Self::Value, E> {
-            value.try_into().map_err(E::custom)
-        }
-    }
-
-    let index = de.deserialize_u32(DescriptorVisitor)? as usize;
-    take_descriptor(index).map_err(D::Error::custom)
-}
-
-/// Allows the use of any serde deserializer within a closure while providing access to the a set of
-/// descriptors for use in `deserialize_descriptor`.
-///
-/// This is the corresponding call to use deserialize after using `SerializeDescriptors`.
-///
-/// If `deserialize_with_descriptors` is called anywhere within the given closure, it return an
-/// error.
-pub fn deserialize_with_descriptors<F, T, E>(
-    f: F,
-    descriptors: &mut Vec<Option<SafeDescriptor>>,
-) -> Result<T, E>
-where
-    F: FnOnce() -> Result<T, E>,
-    E: de::Error,
-{
-    let swap_descriptors = std::mem::take(descriptors);
-    set_descriptor_src(swap_descriptors).map_err(E::custom)?;
-
-    // catch_unwind is used to ensure that set_descriptor_src is always balanced with a call to
-    // take_descriptor_src afterwards.
-    let res = catch_unwind(AssertUnwindSafe(f));
-
-    // unwrap is used because set_descriptor_src is always called before this, so it should never
-    // panic.
-    *descriptors = take_descriptor_src().unwrap();
-
-    match res {
-        Ok(r) => r,
-        Err(e) => resume_unwind(e),
-    }
-}
-
-/// Module that exports `serialize`/`deserialize` functions for use with `#[serde(with = "...")]`
-/// attribute. It only works with fields with `RawDescriptor` type.
-///
-/// # Examples
-///
-/// ```
-/// use serde::{Deserialize, Serialize};
-/// use crate::platform::RawDescriptor;
-///
-/// #[derive(Serialize, Deserialize)]
-/// struct RawContainer {
-///     #[serde(with = "crate::platform::with_raw_descriptor")]
-///     rd: RawDescriptor,
-/// }
-/// ```
-pub mod with_raw_descriptor {
-    use super::super::{IntoRawDescriptor, RawDescriptor};
-    use serde::Deserializer;
-
-    pub use super::serialize_descriptor as serialize;
-
-    pub fn deserialize<'de, D>(de: D) -> std::result::Result<RawDescriptor, D::Error>
-    where
-        D: Deserializer<'de>,
-    {
-        super::deserialize_descriptor(de).map(IntoRawDescriptor::into_raw_descriptor)
-    }
-}
-
-/// Module that exports `serialize`/`deserialize` functions for use with `#[serde(with = "...")]`
-/// attribute.
-///
-/// # Examples
-///
-/// ```
-/// use std::fs::File;
-/// use serde::{Deserialize, Serialize};
-/// use crate::platform::RawDescriptor;
-///
-/// #[derive(Serialize, Deserialize)]
-/// struct FileContainer {
-///     #[serde(with = "crate::platform::with_as_descriptor")]
-///     file: File,
-/// }
-/// ```
-pub mod with_as_descriptor {
-    use super::super::{AsRawDescriptor, FromRawDescriptor, IntoRawDescriptor};
-    use serde::{Deserializer, Serializer};
-
-    pub fn serialize<S: Serializer>(
-        rd: &dyn AsRawDescriptor,
-        se: S,
-    ) -> std::result::Result<S::Ok, S::Error> {
-        super::serialize_descriptor(&rd.as_raw_descriptor(), se)
-    }
-
-    pub fn deserialize<'de, D, T>(de: D) -> std::result::Result<T, D::Error>
-    where
-        D: Deserializer<'de>,
-        T: FromRawDescriptor,
-    {
-        super::deserialize_descriptor(de)
-            .map(IntoRawDescriptor::into_raw_descriptor)
-            .map(|rd| unsafe { T::from_raw_descriptor(rd) })
-    }
-}
-
-/// A simple wrapper around `File` that implements `Serialize`/`Deserialize`, which is useful when
-/// the `#[serde(with = "with_as_descriptor")]` trait is infeasible, such as for a field with type
-/// `Option<File>`.
-#[derive(Serialize, Deserialize)]
-#[serde(transparent)]
-pub struct FileSerdeWrapper(#[serde(with = "with_as_descriptor")] pub File);
-
-impl fmt::Debug for FileSerdeWrapper {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
-impl From<File> for FileSerdeWrapper {
-    fn from(file: File) -> Self {
-        FileSerdeWrapper(file)
-    }
-}
-
-impl From<FileSerdeWrapper> for File {
-    fn from(f: FileSerdeWrapper) -> File {
-        f.0
-    }
-}
-
-impl Deref for FileSerdeWrapper {
-    type Target = File;
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-
-impl DerefMut for FileSerdeWrapper {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.0
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::super::{
-        deserialize_with_descriptors, with_as_descriptor, with_raw_descriptor, FileSerdeWrapper,
-        FromRawDescriptor, RawDescriptor, SafeDescriptor, SerializeDescriptors,
-    };
-
-    use std::{collections::HashMap, fs::File, mem::ManuallyDrop, os::unix::io::AsRawFd};
-
-    use serde::{de::DeserializeOwned, Deserialize, Serialize};
-    use tempfile::tempfile;
-
-    fn deserialize<T: DeserializeOwned>(json: &str, descriptors: &[RawDescriptor]) -> T {
-        let mut safe_descriptors = descriptors
-            .iter()
-            .map(|&v| Some(unsafe { SafeDescriptor::from_raw_descriptor(v) }))
-            .collect();
-
-        let res =
-            deserialize_with_descriptors(|| serde_json::from_str(json), &mut safe_descriptors)
-                .unwrap();
-
-        assert!(safe_descriptors.iter().all(|v| v.is_none()));
-
-        res
-    }
-
-    #[test]
-    fn raw() {
-        #[derive(Serialize, Deserialize, PartialEq, Debug)]
-        struct RawContainer {
-            #[serde(with = "with_raw_descriptor")]
-            rd: RawDescriptor,
-        }
-        // Specifically chosen to not overlap a real descriptor to avoid having to allocate any
-        // descriptors for this test.
-        let fake_rd = 5_123_457_i32;
-        let v = RawContainer { rd: fake_rd };
-        let v_serialize = SerializeDescriptors::new(&v);
-        let json = serde_json::to_string(&v_serialize).unwrap();
-        let descriptors = v_serialize.into_descriptors();
-        let res = deserialize(&json, &descriptors);
-        assert_eq!(v, res);
-    }
-
-    #[test]
-    fn file() {
-        #[derive(Serialize, Deserialize)]
-        struct FileContainer {
-            #[serde(with = "with_as_descriptor")]
-            file: File,
-        }
-
-        let v = FileContainer {
-            file: tempfile().unwrap(),
-        };
-        let v_serialize = SerializeDescriptors::new(&v);
-        let json = serde_json::to_string(&v_serialize).unwrap();
-        let descriptors = v_serialize.into_descriptors();
-        let v = ManuallyDrop::new(v);
-        let res: FileContainer = deserialize(&json, &descriptors);
-        assert_eq!(v.file.as_raw_fd(), res.file.as_raw_fd());
-    }
-
-    #[test]
-    fn option() {
-        #[derive(Serialize, Deserialize)]
-        struct TestOption {
-            a: Option<FileSerdeWrapper>,
-            b: Option<FileSerdeWrapper>,
-        }
-
-        let v = TestOption {
-            a: None,
-            b: Some(tempfile().unwrap().into()),
-        };
-        let v_serialize = SerializeDescriptors::new(&v);
-        let json = serde_json::to_string(&v_serialize).unwrap();
-        let descriptors = v_serialize.into_descriptors();
-        let v = ManuallyDrop::new(v);
-        let res: TestOption = deserialize(&json, &descriptors);
-        assert!(res.a.is_none());
-        assert!(res.b.is_some());
-        assert_eq!(
-            v.b.as_ref().unwrap().as_raw_fd(),
-            res.b.unwrap().as_raw_fd()
-        );
-    }
-
-    #[test]
-    fn map() {
-        let mut v: HashMap<String, FileSerdeWrapper> = HashMap::new();
-        v.insert("a".into(), tempfile().unwrap().into());
-        v.insert("b".into(), tempfile().unwrap().into());
-        v.insert("c".into(), tempfile().unwrap().into());
-        let v_serialize = SerializeDescriptors::new(&v);
-        let json = serde_json::to_string(&v_serialize).unwrap();
-        let descriptors = v_serialize.into_descriptors();
-        // Prevent the files in `v` from dropping while allowing the HashMap itself to drop. It is
-        // done this way to prevent a double close of the files (which should reside in `res`)
-        // without triggering the leak sanitizer on `v`'s HashMap heap memory.
-        let v: HashMap<_, _> = v
-            .into_iter()
-            .map(|(k, v)| (k, ManuallyDrop::new(v)))
-            .collect();
-        let res: HashMap<String, FileSerdeWrapper> = deserialize(&json, &descriptors);
-
-        assert_eq!(v.len(), res.len());
-        for (k, v) in v.iter() {
-            assert_eq!(res.get(k).unwrap().as_raw_fd(), v.as_raw_fd());
-        }
-    }
-}
diff --git a/base/src/unix/mod.rs b/base/src/unix/mod.rs
index def9f7d..f722e0a 100644
--- a/base/src/unix/mod.rs
+++ b/base/src/unix/mod.rs
@@ -27,7 +27,6 @@
 mod capabilities;
 mod clock;
 mod descriptor;
-mod descriptor_reflection;
 mod eventfd;
 mod file_flags;
 pub mod file_traits;
@@ -52,6 +51,10 @@
 pub mod vsock;
 mod write_zeroes;
 
+pub use crate::descriptor_reflection::{
+    deserialize_with_descriptors, with_as_descriptor, with_raw_descriptor, FileSerdeWrapper,
+    SerializeDescriptors,
+};
 pub use crate::{
     common::{Error, Result, *},
     generate_scoped_event,
@@ -61,10 +64,6 @@
 pub use capabilities::drop_capabilities;
 pub use clock::{Clock, FakeClock};
 pub use descriptor::*;
-pub use descriptor_reflection::{
-    deserialize_with_descriptors, with_as_descriptor, with_raw_descriptor, FileSerdeWrapper,
-    SerializeDescriptors,
-};
 pub use eventfd::*;
 pub use file_flags::*;
 pub use fork::*;
diff --git a/base/src/windows/mod.rs b/base/src/windows/mod.rs
index e3b5bee..b0cca80 100644
--- a/base/src/windows/mod.rs
+++ b/base/src/windows/mod.rs
@@ -18,7 +18,6 @@
 #[path = "win/console.rs"]
 mod console;
 mod descriptor;
-mod descriptor_reflection;
 #[path = "win/event.rs"]
 mod event;
 mod events;
@@ -45,14 +44,14 @@
 mod write_zeroes;
 
 pub use crate::common::{Error, Result, *};
+pub use crate::descriptor_reflection::{
+    deserialize_with_descriptors, with_as_descriptor, with_raw_descriptor, FileSerdeWrapper,
+    SerializeDescriptors,
+};
 pub use base_poll_token_derive::*;
 pub use clock::{Clock, FakeClock};
 pub use console::*;
 pub use descriptor::*;
-pub use descriptor_reflection::{
-    deserialize_with_descriptors, with_as_descriptor, with_raw_descriptor, FileSerdeWrapper,
-    SerializeDescriptors,
-};
 pub use event::*;
 pub use events::*;
 pub use get_filesystem_type::*;