Repository: near/borsh-rs (rust)

Issue:
the trait `BorshSerialize` is not implemented for `PhantomData<MyMarker>`
serialize it to 0 bytes

Pull request description:
feat: impl (de)ser for PhantomData
closes #30 

There is another option, which is to serialize a unit struct for the phantom data, similar to serde does by default. If this is done, possibly also schema can be added for it, otherwise, I don't think schema would work for this.

Patch:
diff --git a/borsh/src/de/mod.rs b/borsh/src/de/mod.rs
index 3b7f10f5..236cabf9 100644
--- a/borsh/src/de/mod.rs
+++ b/borsh/src/de/mod.rs
@@ -1,3 +1,4 @@
+use core::marker::PhantomData;
 use core::{
     convert::{TryFrom, TryInto},
     hash::{BuildHasher, Hash},
@@ -583,3 +584,9 @@ where
         Ok(T::Owned::deserialize(buf)?.into())
     }
 }
+
+impl<T: ?Sized> BorshDeserialize for PhantomData<T> {
+    fn deserialize(_: &mut &[u8]) -> Result<Self> {
+        Ok(Self::default())
+    }
+}
diff --git a/borsh/src/ser/mod.rs b/borsh/src/ser/mod.rs
index e01d6632..c3e4c176 100644
--- a/borsh/src/ser/mod.rs
+++ b/borsh/src/ser/mod.rs
@@ -1,5 +1,6 @@
 use core::convert::TryFrom;
 use core::hash::BuildHasher;
+use core::marker::PhantomData;
 
 use crate::maybestd::{
     borrow::{Cow, ToOwned},
@@ -503,3 +504,9 @@ impl<T: BorshSerialize + ?Sized> BorshSerialize for Arc<T> {
         (**self).serialize(writer)
     }
 }
+
+impl<T: ?Sized> BorshSerialize for PhantomData<T> {
+    fn serialize<W: Write>(&self, _: &mut W) -> Result<()> {
+        Ok(())
+    }
+}


Test patch:
diff --git a/borsh/tests/test_generic_struct.rs b/borsh/tests/test_generic_struct.rs
index 9fd0138a..f48056e1 100644
--- a/borsh/tests/test_generic_struct.rs
+++ b/borsh/tests/test_generic_struct.rs
@@ -1,3 +1,5 @@
+use core::marker::PhantomData;
+
 use borsh::{BorshDeserialize, BorshSerialize};
 
 #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
@@ -5,6 +7,7 @@ struct A<T, F, G> {
     x: Vec<T>,
     y: String,
     b: B<F, G>,
+    pd: PhantomData<T>,
     c: std::result::Result<T, G>,
     d: [u64; 5],
 }
@@ -19,6 +22,7 @@ enum B<F, G> {
 fn test_generic_struct() {
     let a = A::<String, u64, String> {
         x: vec!["foo".to_string(), "bar".to_string()],
+        pd: Default::default(),
         y: "world".to_string(),
         b: B::X { f: vec![1, 2] },
         c: Err("error".to_string()),