From 4e88f104c5d2bba2fb9c391ed046869065bb0b45 Mon Sep 17 00:00:00 2001
From: James Munns <james.munns@ferrous-systems.com>
Date: Tue, 12 Nov 2019 00:54:05 +0100
Subject: [PATCH 1/6] Add proof of concept serde support with PathBuf

---
 Cargo.toml          | 5 +++++
 src/path/pathbuf.rs | 4 ++++
 2 files changed, 9 insertions(+)

diff --git a/Cargo.toml b/Cargo.toml
index c1c686555..45ea88ed6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,10 +33,14 @@ default = [
   "mio-uds",
   "num_cpus",
   "pin-project-lite",
+  "serde-remotes",
 ]
 docs = ["attributes", "unstable"]
 unstable = ["default", "broadcaster"]
 attributes = ["async-attributes"]
+serde-support = [
+  "serde",
+]
 std = [
   "async-macros",
   "crossbeam-utils",
@@ -70,6 +74,7 @@ once_cell = { version = "1.2.0", optional = true }
 pin-project-lite = { version = "0.1", optional = true }
 pin-utils = { version = "0.1.0-alpha.4", optional = true }
 slab = { version = "0.4.2", optional = true }
+serde = { version = "1.0.0", optional = true, features = ["derive"] }
 
 [dev-dependencies]
 femme = "1.2.0"
diff --git a/src/path/pathbuf.rs b/src/path/pathbuf.rs
index 56a63a47e..f7b9f61be 100644
--- a/src/path/pathbuf.rs
+++ b/src/path/pathbuf.rs
@@ -13,12 +13,16 @@ use crate::path::Path;
 use crate::prelude::*;
 #[cfg(feature = "unstable")]
 use crate::stream::{self, FromStream, IntoStream};
+#[cfg(feature = "serde-support")]
+use serde::{Serialize, Deserialize};
 
 /// This struct is an async version of [`std::path::PathBuf`].
 ///
 /// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html
+#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
 #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct PathBuf {
+    #[cfg_attr(feature = "serde-support", serde(flatten))]
     inner: std::path::PathBuf,
 }
 

From bcc134cd025b335d6debf93cdebf1d1354bc81fa Mon Sep 17 00:00:00 2001
From: James Munns <james.munns@ferrous-systems.com>
Date: Tue, 12 Nov 2019 00:57:21 +0100
Subject: [PATCH 2/6] Fix feature name

---
 Cargo.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Cargo.toml b/Cargo.toml
index 45ea88ed6..4505afb93 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,7 +33,7 @@ default = [
   "mio-uds",
   "num_cpus",
   "pin-project-lite",
-  "serde-remotes",
+  "serde-support",
 ]
 docs = ["attributes", "unstable"]
 unstable = ["default", "broadcaster"]

From c5a757fb605c7fbe03e3c62a9791f34ffe0c1314 Mon Sep 17 00:00:00 2001
From: James Munns <james.munns@ferrous-systems.com>
Date: Tue, 12 Nov 2019 01:18:09 +0100
Subject: [PATCH 3/6] Add default as a serde dependency

---
 Cargo.toml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Cargo.toml b/Cargo.toml
index 4505afb93..cf9f89f00 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,7 @@ docs = ["attributes", "unstable"]
 unstable = ["default", "broadcaster"]
 attributes = ["async-attributes"]
 serde-support = [
+  "default",
   "serde",
 ]
 std = [
@@ -74,7 +75,7 @@ once_cell = { version = "1.2.0", optional = true }
 pin-project-lite = { version = "0.1", optional = true }
 pin-utils = { version = "0.1.0-alpha.4", optional = true }
 slab = { version = "0.4.2", optional = true }
-serde = { version = "1.0.0", optional = true, features = ["derive"] }
+serde = { version = "1.0.0", optional = true, default-features = false, features = ["derive"] }
 
 [dev-dependencies]
 femme = "1.2.0"

From 6b0a81012b250983f5bb8242c0bc6c14d44ce6c8 Mon Sep 17 00:00:00 2001
From: James Munns <james.munns@ferrous-systems.com>
Date: Tue, 12 Nov 2019 01:28:38 +0100
Subject: [PATCH 4/6] Just use serde as a feature directly

---
 Cargo.toml          | 6 +-----
 src/path/pathbuf.rs | 6 +++---
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index cf9f89f00..ed0d39170 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,15 +33,11 @@ default = [
   "mio-uds",
   "num_cpus",
   "pin-project-lite",
-  "serde-support",
+  "serde",
 ]
 docs = ["attributes", "unstable"]
 unstable = ["default", "broadcaster"]
 attributes = ["async-attributes"]
-serde-support = [
-  "default",
-  "serde",
-]
 std = [
   "async-macros",
   "crossbeam-utils",
diff --git a/src/path/pathbuf.rs b/src/path/pathbuf.rs
index f7b9f61be..386acbf7e 100644
--- a/src/path/pathbuf.rs
+++ b/src/path/pathbuf.rs
@@ -13,16 +13,16 @@ use crate::path::Path;
 use crate::prelude::*;
 #[cfg(feature = "unstable")]
 use crate::stream::{self, FromStream, IntoStream};
-#[cfg(feature = "serde-support")]
+#[cfg(feature = "serde")]
 use serde::{Serialize, Deserialize};
 
 /// This struct is an async version of [`std::path::PathBuf`].
 ///
 /// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html
-#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct PathBuf {
-    #[cfg_attr(feature = "serde-support", serde(flatten))]
+    #[cfg_attr(feature = "serde", serde(flatten))]
     inner: std::path::PathBuf,
 }
 

From 3c92ffeb5cf2be4014aa367a9ed2dd8f4b083463 Mon Sep 17 00:00:00 2001
From: James Munns <james.munns@ferrous-systems.com>
Date: Tue, 12 Nov 2019 01:39:38 +0100
Subject: [PATCH 5/6] Add docs to feature section

---
 src/lib.rs | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/lib.rs b/src/lib.rs
index ddc6462ca..f015e614b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -171,6 +171,18 @@
 //! features = ["attributes"]
 //! ```
 //!
+//! When the `serde` feature is enabled, it is possible to use `async_std` types such as [`path::PathBuf`]
+//! within types that are serialized or deserialized using [`serde`] compatible crates.
+//!
+//! [`serde`]: https://serde.rs
+//! [`path::PathBuf`]: path/struct.PathBuf.html
+//!
+//! ```toml
+//! [dependencies.async-std]
+//! version = "1.0.0"
+//! features = ["serde"]
+//! ```
+//!
 //! Additionally it's possible to only use the core traits and combinators by
 //! only enabling the `std` Cargo feature:
 //!

From c70f00e915053c9dc43ef10cbe72fe3fc7a3a990 Mon Sep 17 00:00:00 2001
From: James Munns <james.munns@ferrous-systems.com>
Date: Tue, 12 Nov 2019 03:22:04 +0100
Subject: [PATCH 6/6] Go from wrapper struct to newtype

---
 src/path/pathbuf.rs | 33 +++++++++++++++------------------
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/src/path/pathbuf.rs b/src/path/pathbuf.rs
index 386acbf7e..a25a6d5aa 100644
--- a/src/path/pathbuf.rs
+++ b/src/path/pathbuf.rs
@@ -21,10 +21,7 @@ use serde::{Serialize, Deserialize};
 /// [`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct PathBuf {
-    #[cfg_attr(feature = "serde", serde(flatten))]
-    inner: std::path::PathBuf,
-}
+pub struct PathBuf(std::path::PathBuf);
 
 impl PathBuf {
     /// Allocates an empty `PathBuf`.
@@ -53,7 +50,7 @@ impl PathBuf {
     /// assert_eq!(Path::new("/test"), p.as_path());
     /// ```
     pub fn as_path(&self) -> &Path {
-        self.inner.as_path().into()
+        self.0.as_path().into()
     }
 
     /// Extends `self` with `path`.
@@ -88,7 +85,7 @@ impl PathBuf {
     /// assert_eq!(path, PathBuf::from("/etc"));
     /// ```
     pub fn push<P: AsRef<Path>>(&mut self, path: P) {
-        self.inner.push(path.as_ref())
+        self.0.push(path.as_ref())
     }
 
     /// Truncates `self` to [`self.parent`].
@@ -112,7 +109,7 @@ impl PathBuf {
     /// assert_eq!(Path::new("/"), p);
     /// ```
     pub fn pop(&mut self) -> bool {
-        self.inner.pop()
+        self.0.pop()
     }
 
     /// Updates [`self.file_name`] to `file_name`.
@@ -142,7 +139,7 @@ impl PathBuf {
     /// assert!(buf == PathBuf::from("/baz.txt"));
     /// ```
     pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
-        self.inner.set_file_name(file_name)
+        self.0.set_file_name(file_name)
     }
 
     /// Updates [`self.extension`] to `extension`.
@@ -171,7 +168,7 @@ impl PathBuf {
     /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path());
     /// ```
     pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
-        self.inner.set_extension(extension)
+        self.0.set_extension(extension)
     }
 
     /// Consumes the `PathBuf`, returning its internal [`OsString`] storage.
@@ -187,7 +184,7 @@ impl PathBuf {
     /// let os_str = p.into_os_string();
     /// ```
     pub fn into_os_string(self) -> OsString {
-        self.inner.into_os_string()
+        self.0.into_os_string()
     }
 
     /// Converts this `PathBuf` into a [boxed][`Box`] [`Path`].
@@ -195,7 +192,7 @@ impl PathBuf {
     /// [`Box`]: https://doc.rust-lang.org/std/boxed/struct.Box.html
     /// [`Path`]: struct.Path.html
     pub fn into_boxed_path(self) -> Box<Path> {
-        let rw = Box::into_raw(self.inner.into_boxed_path()) as *mut Path;
+        let rw = Box::into_raw(self.0.into_boxed_path()) as *mut Path;
         unsafe { Box::from_raw(rw) }
     }
 }
@@ -227,13 +224,13 @@ impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
 
 impl From<OsString> for PathBuf {
     fn from(s: OsString) -> PathBuf {
-        PathBuf { inner: s.into() }
+        PathBuf(s.into())
     }
 }
 
 impl From<PathBuf> for OsString {
     fn from(path_buf: PathBuf) -> OsString {
-        path_buf.inner.into()
+        path_buf.0.into()
     }
 }
 
@@ -269,7 +266,7 @@ impl Deref for PathBuf {
     type Target = Path;
 
     fn deref(&self) -> &Path {
-        Path::new(&self.inner)
+        Path::new(&self.0)
     }
 }
 
@@ -318,7 +315,7 @@ impl From<PathBuf> for Rc<Path> {
 
 impl AsRef<OsStr> for PathBuf {
     fn as_ref(&self) -> &OsStr {
-        self.inner.as_ref()
+        self.0.as_ref()
     }
 }
 
@@ -359,18 +356,18 @@ impl<'b, P: AsRef<Path> + 'b> FromStream<P> for PathBuf {
 
 impl From<std::path::PathBuf> for PathBuf {
     fn from(path: std::path::PathBuf) -> PathBuf {
-        PathBuf { inner: path }
+        PathBuf(path)
     }
 }
 
 impl Into<std::path::PathBuf> for PathBuf {
     fn into(self) -> std::path::PathBuf {
-        self.inner
+        self.0
     }
 }
 
 impl AsRef<std::path::Path> for PathBuf {
     fn as_ref(&self) -> &std::path::Path {
-        self.inner.as_ref()
+        self.0.as_ref()
     }
 }