Repository: near/borsh-rs
Pull request #36 (2021-06-25 18:47:50)

feat: implement schema for arrays and fix box bounds
- Fixes Box impl for schema to not require sized
- implement schema for array `[T]` types and `str`
  - The schema name for array I just made `Vec<T>` but let me know if something else is ideal. I couldn't use `Array<T, len>` because the type itself doesn't have a size

Edit: Also noticed `usize` and `isize` aren't implemented for schema it seems, ideas on if this should be an issue, completed in this PR, or ignored?


Patch:
diff --git a/borsh/src/schema.rs b/borsh/src/schema.rs
index 559e259c..c5a94d24 100644
--- a/borsh/src/schema.rs
+++ b/borsh/src/schema.rs
@@ -104,7 +104,7 @@ pub trait BorshSchema {
 
 impl<T> BorshSchema for Box<T>
 where
-    T: BorshSchema,
+    T: BorshSchema + ?Sized,
 {
     fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
         T::add_definitions_recursively(definitions);
@@ -144,6 +144,7 @@ macro_rules! impl_for_primitives {
 
 impl_for_primitives!(bool char f32 f64 i8 i16 i32 i64 i128 u8 u16 u32 u64 u128);
 impl_for_renamed_primitives!(String: string);
+impl_for_renamed_primitives!(str: string);
 
 macro_rules! impl_arrays {
     ($($len:expr)+) => {
@@ -225,6 +226,23 @@ where
     }
 }
 
+impl<T> BorshSchema for [T]
+where
+    T: BorshSchema,
+{
+    fn add_definitions_recursively(definitions: &mut HashMap<Declaration, Definition>) {
+        let definition = Definition::Sequence {
+            elements: T::declaration(),
+        };
+        Self::add_definition(Self::declaration(), definition, definitions);
+        T::add_definitions_recursively(definitions);
+    }
+
+    fn declaration() -> Declaration {
+        format!(r#"Vec<{}>"#, T::declaration())
+    }
+}
+
 impl<K, V> BorshSchema for HashMap<K, V>
 where
     K: BorshSchema,
@@ -460,4 +478,23 @@ mod tests {
             actual_defs
         );
     }
+
+    #[test]
+    fn string() {
+        let actual_name = str::declaration();
+        assert_eq!("string", actual_name);
+        let actual_name = String::declaration();
+        assert_eq!("string", actual_name);
+        let mut actual_defs = map!();
+        String::add_definitions_recursively(&mut actual_defs);
+        assert_eq!(map! {}, actual_defs);
+    }
+
+    #[test]
+    fn boxed_schema() {
+        let boxed_declaration = Box::<str>::declaration();
+        assert_eq!("string", boxed_declaration);
+        let boxed_declaration = Box::<[u8]>::declaration();
+        assert_eq!("Vec<u8>", boxed_declaration);
+    }
 }


Test patch:
diff --git a/borsh/tests/test_schema_nested.rs b/borsh/tests/test_schema_nested.rs
index 980adbf7..ea2f181a 100644
--- a/borsh/tests/test_schema_nested.rs
+++ b/borsh/tests/test_schema_nested.rs
@@ -26,12 +26,12 @@ pub fn duplicated_instantiations() {
     struct Oil<K, V> {
         seeds: HashMap<K, V>,
         liquid: Option<K>,
-    };
+    }
     #[derive(borsh::BorshSchema)]
     struct Wrapper<T> {
         foo: Option<T>,
         bar: Box<A<T, T>>,
-    };
+    }
     #[derive(borsh::BorshSchema)]
     struct Filling;
     #[derive(borsh::BorshSchema)]
diff --git a/borsh/tests/test_schema_structs.rs b/borsh/tests/test_schema_structs.rs
index 76f67ce8..ea258563 100644
--- a/borsh/tests/test_schema_structs.rs
+++ b/borsh/tests/test_schema_structs.rs
@@ -35,7 +35,7 @@ pub fn simple_struct() {
     struct A {
         _f1: u64,
         _f2: String,
-    };
+    }
     assert_eq!("A".to_string(), A::declaration());
     let mut defs = Default::default();
     A::add_definitions_recursively(&mut defs);
@@ -50,6 +50,30 @@ pub fn simple_struct() {
     );
 }
 
+#[test]
+pub fn boxed() {
+    #[derive(borsh::BorshSchema)]
+    struct A {
+        _f1: Box<u64>,
+        _f2: Box<str>,
+        _f3: Box<[u8]>,
+    }
+    assert_eq!("A".to_string(), A::declaration());
+    let mut defs = Default::default();
+    A::add_definitions_recursively(&mut defs);
+    assert_eq!(
+        map! {
+        "Vec<u8>" => Definition::Sequence { elements: "u8".to_string() },
+        "A" => Definition::Struct{ fields: Fields::NamedFields(vec![
+        ("_f1".to_string(), "u64".to_string()),
+        ("_f2".to_string(), "string".to_string()),
+        ("_f3".to_string(), "Vec<u8>".to_string())
+        ])}
+        },
+        defs
+    );
+}
+
 #[test]
 pub fn wrapper_struct() {
     #[derive(borsh::BorshSchema)]
@@ -108,7 +132,7 @@ pub fn simple_generics() {
     struct A<K, V> {
         _f1: HashMap<K, V>,
         _f2: String,
-    };
+    }
     assert_eq!(
         "A<u64, string>".to_string(),
         <A<u64, String>>::declaration()