Skip to content

Commit

Permalink
feat: impl BorshSchema for Cow<'a, T> (#284)
Browse files Browse the repository at this point in the history
* test: correct `test_ultimate_combined_all_features` test expected return type variant for Cow

impl<'a, 'b, B, C> PartialEq<Cow<'b, C>> for Cow<'a, B>
where
    B: PartialEq<C> + ToOwned + ?Sized,
    C: ToOwned + ?Sized,
allowed to use `Cow::Borrowed` instead of `Cow::Owned`

* test: add `test_cow`

* feat: impl `BorshSchema` for `Cow<'a, T>`
  • Loading branch information
dj8yfo committed Feb 29, 2024
1 parent fbcfd1d commit 5f33c59
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 1 deletion.
15 changes: 15 additions & 0 deletions borsh/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#![allow(dead_code)] // Unclear why rust check complains on fields of `Definition` variants.
use crate as borsh; // For `#[derive(BorshSerialize, BorshDeserialize)]`.
use crate::__private::maybestd::{
borrow,
boxed::Box,
collections::{btree_map::Entry, BTreeMap, BTreeSet},
format,
Expand Down Expand Up @@ -382,6 +383,20 @@ pub mod rc {
}
}

impl<T> BorshSchema for borrow::Cow<'_, T>
where
T: borrow::ToOwned + ?Sized,
T::Owned: BorshSchema,
{
fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
<T::Owned as BorshSchema>::add_definitions_recursively(definitions);
}

fn declaration() -> Declaration {
<T::Owned as BorshSchema>::declaration()
}
}

macro_rules! impl_for_renamed_primitives {
($($ty: ty : $name: ident => $size: expr);+) => {
$(
Expand Down
20 changes: 20 additions & 0 deletions borsh/tests/snapshots/test_cow__cow_byte_slice.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
source: borsh/tests/test_cow.rs
expression: encoded
---
[
10,
0,
0,
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
]
55 changes: 55 additions & 0 deletions borsh/tests/snapshots/test_cow__cow_slice_of_cow_str.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
source: borsh/tests/test_cow.rs
expression: encoded
---
[
2,
0,
0,
0,
18,
0,
0,
0,
102,
105,
114,
115,
116,
32,
115,
116,
97,
116,
105,
99,
32,
105,
110,
112,
117,
116,
19,
0,
0,
0,
115,
101,
99,
111,
110,
100,
32,
115,
116,
97,
116,
105,
99,
32,
105,
110,
112,
117,
116,
]
22 changes: 22 additions & 0 deletions borsh/tests/snapshots/test_cow__cow_str.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
source: borsh/tests/test_cow.rs
expression: encoded
---
[
12,
0,
0,
0,
115,
116,
97,
116,
105,
99,
32,
105,
110,
112,
117,
116,
]
157 changes: 157 additions & 0 deletions borsh/tests/test_cow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#![cfg_attr(not(feature = "std"), no_std)]

use borsh::{from_slice, to_vec};
use core::{matches, ops::Deref};
extern crate alloc;
use alloc::string::ToString;

#[cfg(feature = "std")]
use std::borrow::Cow;

#[cfg(not(feature = "std"))]
use alloc::{borrow::Cow, vec};

#[test]
fn test_cow_str() {
let input: Cow<'_, str> = Cow::Borrowed("static input");

let encoded = to_vec(&input).unwrap();

#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);

let out: Cow<'_, str> = from_slice(&encoded).unwrap();

assert!(matches!(out, Cow::Owned(..)));

assert_eq!(input, out);
assert_eq!(out, "static input");
}

#[test]
fn test_cow_byte_slice() {
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let input: Cow<'_, [u8]> = Cow::Borrowed(&arr);

let encoded = to_vec(&input).unwrap();

#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);

let out: Cow<'_, [u8]> = from_slice(&encoded).unwrap();

assert!(matches!(out, Cow::Owned(..)));

assert_eq!(input, out);
assert_eq!(out, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}

#[test]
fn test_cow_slice_of_cow_str() {
let arr = [
Cow::Borrowed("first static input"),
Cow::Owned("second static input".to_string()),
];
let input: Cow<'_, [Cow<'_, str>]> = Cow::Borrowed(&arr);

let encoded = to_vec(&input).unwrap();

#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);

let out: Cow<'_, [Cow<'_, str>]> = from_slice(&encoded).unwrap();

assert!(matches!(out, Cow::Owned(..)));

for element in out.deref() {
assert!(matches!(element, Cow::Owned(..)));
}

assert_eq!(input, out);
assert_eq!(
out,
vec![
Cow::Borrowed("first static input"),
Cow::Borrowed("second static input"),
]
);
}

#[macro_use]
mod common_macro;

#[cfg(feature = "unstable__schema")]
mod schema {

use super::common_macro::schema_imports::*;
#[cfg(feature = "std")]
use std::borrow::Cow;

#[cfg(not(feature = "std"))]
use alloc::borrow::Cow;

#[test]
fn test_cow_str() {
assert_eq!("String", <Cow<'_, str> as BorshSchema>::declaration());

let mut actual_defs = schema_map!();
<Cow<'_, str> as BorshSchema>::add_definitions_recursively(&mut actual_defs);
assert_eq!(
schema_map! {
"String" => Definition::Sequence {
length_width: Definition::DEFAULT_LENGTH_WIDTH,
length_range: Definition::DEFAULT_LENGTH_RANGE,
elements: "u8".to_string()
},
"u8" => Definition::Primitive(1)
},
actual_defs
);
}

#[test]
fn test_cow_byte_slice() {
assert_eq!("Vec<u8>", <Cow<'_, [u8]> as BorshSchema>::declaration());

let mut actual_defs = schema_map!();
<Cow<'_, [u8]> as BorshSchema>::add_definitions_recursively(&mut actual_defs);
assert_eq!(
schema_map! {
"Vec<u8>" => Definition::Sequence {
length_width: Definition::DEFAULT_LENGTH_WIDTH,
length_range: Definition::DEFAULT_LENGTH_RANGE,
elements: "u8".to_string(),
},
"u8" => Definition::Primitive(1)
},
actual_defs
);
}

#[test]
fn test_cow_slice_of_cow_str() {
assert_eq!(
"Vec<String>",
<Cow<'_, [Cow<'_, str>]> as BorshSchema>::declaration()
);

let mut actual_defs = schema_map!();
<Cow<'_, [Cow<'_, str>]> as BorshSchema>::add_definitions_recursively(&mut actual_defs);
assert_eq!(
schema_map! {
"Vec<String>" => Definition::Sequence {
length_width: Definition::DEFAULT_LENGTH_WIDTH,
length_range: Definition::DEFAULT_LENGTH_RANGE,
elements: "String".to_string(),
},
"String" => Definition::Sequence {
length_width: Definition::DEFAULT_LENGTH_WIDTH,
length_range: Definition::DEFAULT_LENGTH_RANGE,
elements: "u8".to_string()
},
"u8" => Definition::Primitive(1)
},
actual_defs
);
}
}
2 changes: 1 addition & 1 deletion borsh/tests/test_simple_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ fn test_ultimate_combined_all_features() {
lazy: Some(5),
c: borrow::Cow::Owned("Hello".to_string()),
cow_arr: borrow::Cow::Owned(vec![
borrow::Cow::Borrowed("Hello1"),
borrow::Cow::Owned("Hello1".to_string()),
borrow::Cow::Owned("Hello2".to_string()),
]),
range_u32: 12..71,
Expand Down

0 comments on commit 5f33c59

Please sign in to comment.