Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
@@ -0,0 +1,21 @@
#![allow(clippy::float_cmp)]
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
use bson::oid::ObjectId;
#[derive(BorshDeserialize, BorshSerialize, PartialEq, Debug)]
struct StructWithObjectId(i32, ObjectId, u8);
#[test]
fn test_object_id() {
let obj = StructWithObjectId(
123,
ObjectId::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
33,
);
let serialized = to_vec(&obj).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(serialized);
let deserialized: StructWithObjectId = from_slice(&serialized).unwrap();
assert_eq!(obj, deserialized);
}
@@ -0,0 +1,193 @@
use alloc::vec;
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
// sequence, no unit enums
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Clone, Copy, Debug)]
#[borsh(use_discriminant = true)]
#[repr(u16)]
enum XY {
A,
B = 20,
C,
D(u32, u32),
E = 10,
F(u64),
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Clone, Copy, Debug)]
#[borsh(use_discriminant = false)]
#[repr(u16)]
enum XYNoDiscriminant {
A,
B = 20,
C,
D(u32, u32),
E = 10,
F(u64),
}
#[test]
fn test_discriminant_serde_no_unit_type() {
let values = vec![XY::A, XY::B, XY::C, XY::E, XY::D(12, 14), XY::F(35325423)];
let expected_discriminants = [0u8, 20, 21, 10, 22, 11];
for (ind, value) in values.iter().enumerate() {
let data = to_vec(value).unwrap();
assert_eq!(data[0], expected_discriminants[ind]);
assert_eq!(from_slice::<XY>(&data).unwrap(), values[ind]);
}
}
#[test]
fn test_discriminant_serde_no_unit_type_no_use_discriminant() {
let values = vec![
XYNoDiscriminant::A,
XYNoDiscriminant::B,
XYNoDiscriminant::C,
XYNoDiscriminant::D(12, 14),
XYNoDiscriminant::E,
XYNoDiscriminant::F(35325423),
];
let expected_discriminants = [0u8, 1, 2, 3, 4, 5];
for (ind, value) in values.iter().enumerate() {
let data = to_vec(value).unwrap();
assert_eq!(data[0], expected_discriminants[ind]);
assert_eq!(from_slice::<XYNoDiscriminant>(&data).unwrap(), values[ind]);
}
}
// minimal
#[derive(BorshSerialize)]
#[borsh(use_discriminant = true)]
enum MyDiscriminantEnum {
A = 20,
}
#[derive(BorshSerialize)]
#[borsh(use_discriminant = false)]
enum MyDiscriminantEnumFalse {
A = 20,
}
#[derive(BorshSerialize)]
enum MyEnumNoDiscriminant {
A,
}
#[test]
fn test_discriminant_minimal_true() {
assert_eq!(MyDiscriminantEnum::A as u8, 20);
assert_eq!(to_vec(&MyDiscriminantEnum::A).unwrap(), vec![20]);
}
#[test]
fn test_discriminant_minimal_false() {
assert_eq!(MyDiscriminantEnumFalse::A as u8, 20);
assert_eq!(
to_vec(&MyEnumNoDiscriminant::A).unwrap(),
to_vec(&MyDiscriminantEnumFalse::A).unwrap(),
);
assert_eq!(to_vec(&MyDiscriminantEnumFalse::A).unwrap(), vec![0]);
}
// sequence
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Clone, Copy, Debug)]
#[borsh(use_discriminant = false)]
enum XNoDiscriminant {
A,
B = 20,
C,
D,
E = 10,
F,
}
#[test]
fn test_discriminant_serde_no_use_discriminant() {
let values = vec![
XNoDiscriminant::A,
XNoDiscriminant::B,
XNoDiscriminant::C,
XNoDiscriminant::D,
XNoDiscriminant::E,
XNoDiscriminant::F,
];
let expected_discriminants = [0u8, 1, 2, 3, 4, 5];
for (index, value) in values.iter().enumerate() {
let data = to_vec(value).unwrap();
assert_eq!(data[0], expected_discriminants[index]);
assert_eq!(from_slice::<XNoDiscriminant>(&data).unwrap(), values[index]);
}
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct D {
x: u64,
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
enum C {
C1,
C2(u64),
C3(u64, u64),
C4 { x: u64, y: u64 },
C5(D),
}
#[test]
fn test_enum_tuples() {
let values = vec![
C::C1,
C::C2(u64::MAX),
C::C3(1, 2),
C::C4 { x: 0, y: 100 },
C::C5(D { x: u64::MAX }),
];
for value in values {
assert_eq!(from_slice::<C>(&to_vec(&value).unwrap()).unwrap(), value);
}
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Clone, Copy, Debug)]
#[borsh(use_discriminant = true)]
enum X {
A,
B = 20,
C,
D,
E = 10,
F,
}
#[test]
fn test_discriminant_serialization() {
let values = vec![X::A, X::B, X::C, X::D, X::E, X::F];
for value in values {
assert_eq!(to_vec(&value).unwrap(), [value as u8]);
}
}
#[test]
fn test_discriminant_deserialization() {
let values = vec![X::A, X::B, X::C, X::D, X::E, X::F];
for value in values {
assert_eq!(from_slice::<X>(&[value as u8]).unwrap(), value,);
}
}
#[test]
#[should_panic = "Unexpected variant tag: 2"]
fn test_deserialize_invalid_discriminant() {
from_slice::<X>(&[2]).unwrap();
}
#[test]
fn test_discriminant_serde() {
let values = vec![X::A, X::B, X::C, X::D, X::E, X::F];
let expected_discriminants = [0u8, 20, 21, 22, 10, 11];
for (index, value) in values.iter().enumerate() {
let data = to_vec(value).unwrap();
assert_eq!(data[0], expected_discriminants[index]);
assert_eq!(from_slice::<X>(&data).unwrap(), values[index]);
}
}
@@ -0,0 +1,29 @@
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
use alloc::{
string::{String, ToString},
vec,
vec::Vec,
};
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
enum B<W, G> {
X { f: Vec<W> },
Y(G),
}
#[test]
fn test_generic_enum() {
let b: B<String, u64> = B::X {
f: vec!["one".to_string(), "two".to_string(), "three".to_string()],
};
let c: B<String, u64> = B::Y(656556u64);
let list = vec![b, c];
let data = to_vec(&list).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_list = from_slice::<Vec<B<String, u64>>>(&data).unwrap();
assert_eq!(list, actual_list);
}
@@ -0,0 +1,110 @@
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
use core::marker::PhantomData;
#[cfg(feature = "hashbrown")]
use hashbrown::HashMap;
#[cfg(hash_collections)]
use core::{cmp::Eq, hash::Hash};
#[cfg(feature = "std")]
use std::collections::HashMap;
use alloc::{
string::{ToString, String},
vec,
vec::Vec,
};
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
enum B<W, G> {
X { f: Vec<W> },
Y(G),
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct A<T, F, G> {
x: Vec<T>,
y: String,
b: B<F, G>,
pd: PhantomData<T>,
c: Result<T, G>,
d: [u64; 5],
}
#[test]
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()),
d: [0, 1, 2, 3, 4],
};
let data = to_vec(&a).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_a = from_slice::<A<String, u64, String>>(&data).unwrap();
assert_eq!(a, actual_a);
}
trait TraitName {
type Associated;
#[allow(unused)]
fn method(&self);
}
impl TraitName for u32 {
type Associated = String;
fn method(&self) {}
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct Parametrized<T, V>
where
T: TraitName,
{
field: T::Associated,
another: V,
}
#[test]
fn test_generic_associated_type_field() {
let a = Parametrized::<u32, String> {
field: "value".to_string(),
another: "field".to_string(),
};
let data = to_vec(&a).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_a = from_slice::<Parametrized<u32, String>>(&data).unwrap();
assert_eq!(a, actual_a);
}
/// `T: PartialOrd` bound is required for `BorshSerialize` derive to be successful
/// `T: Hash + Eq` bound is required for `BorshDeserialize` derive to be successful
#[cfg(hash_collections)]
#[derive(BorshSerialize, BorshDeserialize)]
struct C<T: Ord + Hash + Eq, U> {
a: String,
b: HashMap<T, U>,
}
#[cfg(hash_collections)]
#[test]
fn test_generic_struct_hashmap() {
let mut hashmap = HashMap::new();
hashmap.insert(34, "another".to_string());
hashmap.insert(14, "value".to_string());
let a = C::<u32, String> {
a: "field".to_string(),
b: hashmap,
};
let data = to_vec(&a).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_a = from_slice::<C<u32, String>>(&data).unwrap();
assert_eq!(actual_a.b.get(&14), Some("value".to_string()).as_ref());
assert_eq!(actual_a.b.get(&34), Some("another".to_string()).as_ref());
}
@@ -0,0 +1,153 @@
use alloc::{
collections::BTreeMap,
string::{String, ToString},
};
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
// the `BorshSchema` derive expands to code that uses the `format!` macro at the
// struct definition site, so it has to be in scope here too.
#[cfg(feature = "unstable__schema")]
use alloc::format;
#[derive(Debug, PartialEq, Eq)]
struct ThirdParty<K, V>(pub BTreeMap<K, V>);
mod third_party_impl {
use super::ThirdParty;
pub(super) fn serialize_third_party<
K: borsh::ser::BorshSerialize,
V: borsh::ser::BorshSerialize,
W: borsh::io::Write,
>(
obj: &ThirdParty<K, V>,
writer: &mut W,
) -> ::core::result::Result<(), borsh::io::Error> {
borsh::BorshSerialize::serialize(&obj.0, writer)?;
Ok(())
}
pub(super) fn deserialize_third_party<
R: borsh::io::Read,
K: borsh::de::BorshDeserialize + Ord,
V: borsh::de::BorshDeserialize,
>(
reader: &mut R,
) -> ::core::result::Result<ThirdParty<K, V>, borsh::io::Error> {
Ok(ThirdParty(borsh::BorshDeserialize::deserialize_reader(
reader,
)?))
}
#[cfg(feature = "unstable__schema")]
use alloc::{collections::BTreeMap, format, vec};
#[cfg(feature = "unstable__schema")]
pub(super) fn declaration<K: borsh::BorshSchema, V: borsh::BorshSchema>(
) -> borsh::schema::Declaration {
let params = vec![<K>::declaration(), <V>::declaration()];
format!(r#"{}<{}>"#, "ThirdParty", params.join(", "))
}
#[cfg(feature = "unstable__schema")]
pub(super) fn add_definitions_recursively<K: borsh::BorshSchema, V: borsh::BorshSchema>(
definitions: &mut BTreeMap<borsh::schema::Declaration, borsh::schema::Definition>,
) {
let fields = borsh::schema::Fields::UnnamedFields(vec![
<BTreeMap<K, V> as borsh::BorshSchema>::declaration(),
]);
let definition = borsh::schema::Definition::Struct { fields };
let no_recursion_flag = definitions.get(&declaration::<K, V>()).is_none();
borsh::schema::add_definition(declaration::<K, V>(), definition, definitions);
if no_recursion_flag {
<BTreeMap<K, V> as borsh::BorshSchema>::add_definitions_recursively(definitions);
}
}
}
// This mirrors the `near/intents` use case: the common `serialize_with` /
// `deserialize_with` / `bound` part is written once, and the schema-only part
// lives in a separate, `cfg`-gated `#[borsh(...)]` attribute. borsh merges the
// disjoint top-level keys of all `#[borsh(...)]` attributes into one.
#[cfg_attr(feature = "unstable__schema", derive(borsh::BorshSchema))]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug)]
struct A<K, V> {
#[borsh(serialize_with = "third_party_impl::serialize_third_party")]
#[borsh(deserialize_with = "third_party_impl::deserialize_third_party")]
#[borsh(bound(
deserialize = "K: borsh::de::BorshDeserialize + Ord, V: borsh::de::BorshDeserialize",
))]
#[cfg_attr(
feature = "unstable__schema",
borsh(schema(with_funcs(
declaration = "third_party_impl::declaration::<K, V>",
definitions = "third_party_impl::add_definitions_recursively::<K, V>"
)))
)]
x: ThirdParty<K, V>,
y: u64,
}
#[test]
fn test_overridden_struct_multiple_attrs() {
let mut m = BTreeMap::<u64, String>::new();
m.insert(0, "0th element".to_string());
m.insert(1, "1st element".to_string());
let th_p = ThirdParty(m);
let a = A { x: th_p, y: 42 };
let data = to_vec(&a).unwrap();
let actual_a = from_slice::<A<u64, String>>(&data).unwrap();
assert_eq!(a, actual_a);
}
#[cfg(feature = "unstable__schema")]
#[test]
fn test_overridden_struct_multiple_attrs_schema() {
use borsh::BorshSchema;
assert_eq!(
"A<u64, String>".to_string(),
<A<u64, String>>::declaration()
);
let mut defs = Default::default();
<A<u64, String>>::add_definitions_recursively(&mut defs);
// the schema-only `with_funcs` attribute from the separate `#[borsh(...)]`
// block takes effect: `x` resolves to the custom `ThirdParty` declaration.
assert!(defs.contains_key("ThirdParty<u64, String>"));
}
// Item-level merge through the real derive macro: `use_discriminant` lives in
// one `#[borsh(...)]` attribute and `init` in a separate one. Both have to take
// effect for the assertions below to hold.
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug)]
#[borsh(use_discriminant = true)]
#[borsh(init = initialization_method)]
enum WithSplitItemAttrs {
A,
B = 10,
C,
}
impl WithSplitItemAttrs {
fn initialization_method(&mut self) {
*self = WithSplitItemAttrs::C;
}
}
#[test]
fn test_item_level_multiple_attrs() {
let value = WithSplitItemAttrs::B;
let data = to_vec(&value).unwrap();
// `use_discriminant = true` (first attribute) honors the explicit
// discriminant: `B = 10` serializes its tag as the byte `10`, not the
// positional index `1`.
assert_eq!(data, [10]);
// `init = initialization_method` (second attribute) runs after decoding, so
// the deserialized value is rewritten to `C`.
let decoded = from_slice::<WithSplitItemAttrs>(&data).unwrap();
assert_eq!(decoded, WithSplitItemAttrs::C);
}
@@ -0,0 +1,28 @@
use alloc::{
string::{String, ToString},
vec,
vec::Vec,
};
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
enum ERecD {
B { x: String, y: i32 },
C(u8, Vec<ERecD>),
}
#[test]
fn test_recursive_enum() {
let one = ERecD::B {
x: "one".to_string(),
y: 3213123,
};
let two = ERecD::C(10, vec![]);
let three = ERecD::C(11, vec![one, two]);
let data = to_vec(&three).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_three = from_slice::<ERecD>(&data).unwrap();
assert_eq!(three, actual_three);
}
@@ -0,0 +1,31 @@
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
use alloc::{string::{String, ToString}, vec::Vec, vec};
#[derive(Debug, BorshSerialize, BorshDeserialize, PartialEq, Eq)]
struct CRecB {
a: String,
b: Vec<CRecB>,
}
#[test]
fn test_recursive_struct() {
let one = CRecB {
a: "one".to_string(),
b: vec![],
};
let two = CRecB {
a: "two".to_string(),
b: vec![],
};
let three = CRecB {
a: "three".to_string(),
b: vec![one, two],
};
let data = to_vec(&three).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_three = from_slice::<CRecB>(&data).unwrap();
assert_eq!(three, actual_three);
}
@@ -0,0 +1,98 @@
use alloc::{
collections::BTreeMap,
string::{String, ToString},
};
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
#[derive(Debug, PartialEq, Eq)]
struct ThirdParty<K, V>(pub BTreeMap<K, V>);
mod third_party_impl {
use super::ThirdParty;
pub(super) fn serialize_third_party<
K: borsh::ser::BorshSerialize,
V: borsh::ser::BorshSerialize,
W: borsh::io::Write,
>(
obj: &ThirdParty<K, V>,
writer: &mut W,
) -> ::core::result::Result<(), borsh::io::Error> {
borsh::BorshSerialize::serialize(&obj.0, writer)?;
Ok(())
}
pub(super) fn deserialize_third_party<
R: borsh::io::Read,
K: borsh::de::BorshDeserialize + Ord,
V: borsh::de::BorshDeserialize,
>(
reader: &mut R,
) -> ::core::result::Result<ThirdParty<K, V>, borsh::io::Error> {
Ok(ThirdParty(borsh::BorshDeserialize::deserialize_reader(
reader,
)?))
}
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug)]
struct A<K, V> {
#[borsh(
deserialize_with = "third_party_impl::deserialize_third_party",
serialize_with = "third_party_impl::serialize_third_party",
bound(
deserialize = "K: borsh::de::BorshDeserialize + Ord, V: borsh::de::BorshDeserialize",
)
)]
x: ThirdParty<K, V>,
y: u64,
}
#[allow(unused)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug)]
enum C<K, V> {
C3(u64, u64),
C4(
u64,
#[borsh(
deserialize_with = "third_party_impl::deserialize_third_party",
serialize_with = "third_party_impl::serialize_third_party",
bound(
deserialize = "K: borsh::de::BorshDeserialize + Ord, V: borsh::de::BorshDeserialize",
)
)]
ThirdParty<K, V>,
),
}
#[test]
fn test_overriden_struct() {
let mut m = BTreeMap::<u64, String>::new();
m.insert(0, "0th element".to_string());
m.insert(1, "1st element".to_string());
let th_p = ThirdParty(m);
let a = A { x: th_p, y: 42 };
let data = to_vec(&a).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_a = from_slice::<A<u64, String>>(&data).unwrap();
assert_eq!(a, actual_a);
}
#[test]
fn test_overriden_enum() {
let mut m = BTreeMap::<u64, String>::new();
m.insert(0, "0th element".to_string());
m.insert(1, "1st element".to_string());
let th_p = ThirdParty(m);
let c = C::C4(42, th_p);
let data = to_vec(&c).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(data);
let actual_c = from_slice::<C<u64, String>>(&data).unwrap();
assert_eq!(c, actual_c);
}
@@ -0,0 +1,30 @@
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
use alloc::vec;
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
enum MixedWithUnitVariants {
A(u16),
B,
C { x: i32, y: i32 },
D,
}
#[test]
fn test_mixed_enum() {
let vars = vec![
MixedWithUnitVariants::A(13),
MixedWithUnitVariants::B,
MixedWithUnitVariants::C { x: 132, y: -17 },
MixedWithUnitVariants::D,
];
for variant in vars {
let encoded = to_vec(&variant).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);
let decoded = from_slice::<MixedWithUnitVariants>(&encoded).unwrap();
assert_eq!(variant, decoded);
}
}
@@ -0,0 +1,210 @@
use core::{ops, result::Result};
use alloc::{
borrow,
boxed::Box,
collections::{BTreeMap, BTreeSet, LinkedList, VecDeque},
string::{String, ToString},
vec,
vec::Vec,
};
use bytes::{Bytes, BytesMut};
use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize};
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct A<'a> {
x: u64,
b: B,
y: f32,
z: String,
t: (String, u64),
btree_map_string: BTreeMap<String, String>,
btree_set_u64: BTreeSet<u64>,
linked_list_string: LinkedList<String>,
vec_deque_u64: VecDeque<u64>,
bytes: Bytes,
bytes_mut: BytesMut,
v: Vec<String>,
w: Box<[u8]>,
box_str: Box<str>,
i: [u8; 32],
u: Result<String, String>,
lazy: Option<u64>,
c: borrow::Cow<'a, str>,
cow_arr: borrow::Cow<'a, [borrow::Cow<'a, str>]>,
range_u32: ops::Range<u32>,
#[borsh(skip)]
skipped: Option<u64>,
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct B {
x: u64,
y: i32,
c: C,
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
enum C {
C1,
C2(u64),
C3(u64, u64),
C4 { x: u64, y: u64 },
C5(D),
}
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
struct D {
x: u64,
}
#[derive(BorshSerialize)]
struct E<'a, 'b> {
a: &'a A<'b>,
}
#[derive(BorshSerialize)]
struct F1<'a, 'b> {
aa: &'a [&'a A<'b>],
}
#[derive(BorshDeserialize)]
struct F2<'b> {
aa: Vec<A<'b>>,
}
#[test]
fn test_ultimate_combined_all_features() {
let mut map: BTreeMap<String, String> = BTreeMap::new();
map.insert("test".into(), "test".into());
let mut set: BTreeSet<u64> = BTreeSet::new();
set.insert(u64::MAX);
let cow_arr = [
borrow::Cow::Borrowed("Hello1"),
borrow::Cow::Owned("Hello2".to_string()),
];
let a = A {
x: 1,
b: B {
x: 2,
y: 3,
c: C::C5(D { x: 1 }),
},
y: 4.0,
z: "123".to_string(),
t: ("Hello".to_string(), 10),
btree_map_string: map.clone(),
btree_set_u64: set.clone(),
linked_list_string: vec!["a".to_string(), "b".to_string()].into_iter().collect(),
vec_deque_u64: vec![1, 2, 3].into_iter().collect(),
bytes: vec![5, 4, 3, 2, 1].into(),
bytes_mut: BytesMut::from(&[1, 2, 3, 4, 5][..]),
v: vec!["qwe".to_string(), "zxc".to_string()],
w: vec![0].into_boxed_slice(),
box_str: Box::from("asd"),
i: [4u8; 32],
u: Ok("Hello".to_string()),
lazy: Some(5),
c: borrow::Cow::Borrowed("Hello"),
cow_arr: borrow::Cow::Borrowed(&cow_arr),
range_u32: 12..71,
skipped: Some(6),
};
let encoded_a = to_vec(&a).unwrap();
let e = E { a: &a };
let encoded_ref_a = to_vec(&e).unwrap();
assert_eq!(encoded_ref_a, encoded_a);
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded_a);
let decoded_a = from_slice::<A>(&encoded_a).unwrap();
let expected_a = A {
x: 1,
b: B {
x: 2,
y: 3,
c: C::C5(D { x: 1 }),
},
y: 4.0,
z: a.z.clone(),
t: ("Hello".to_string(), 10),
btree_map_string: map,
btree_set_u64: set,
linked_list_string: vec!["a".to_string(), "b".to_string()].into_iter().collect(),
vec_deque_u64: vec![1, 2, 3].into_iter().collect(),
bytes: vec![5, 4, 3, 2, 1].into(),
bytes_mut: BytesMut::from(&[1, 2, 3, 4, 5][..]),
v: a.v.clone(),
w: a.w.clone(),
box_str: Box::from("asd"),
i: a.i,
u: Ok("Hello".to_string()),
lazy: Some(5),
c: borrow::Cow::Owned("Hello".to_string()),
cow_arr: borrow::Cow::Owned(vec![
borrow::Cow::Owned("Hello1".to_string()),
borrow::Cow::Owned("Hello2".to_string()),
]),
range_u32: 12..71,
skipped: None,
};
assert_eq!(expected_a, decoded_a);
let f1 = F1 { aa: &[&a, &a] };
let encoded_f1 = to_vec(&f1).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded_f1);
let decoded_f2 = from_slice::<F2>(&encoded_f1).unwrap();
assert_eq!(decoded_f2.aa.len(), 2);
assert!(decoded_f2.aa.iter().all(|f2_a| f2_a == &expected_a));
}
#[test]
fn test_object_length() {
let mut map: BTreeMap<String, String> = BTreeMap::new();
map.insert("test".into(), "test".into());
let mut set: BTreeSet<u64> = BTreeSet::new();
set.insert(u64::MAX);
set.insert(100);
set.insert(103);
set.insert(109);
let cow_arr = [
borrow::Cow::Borrowed("Hello1"),
borrow::Cow::Owned("Hello2".to_string()),
];
let a = A {
x: 1,
b: B {
x: 2,
y: 3,
c: C::C5(D { x: 1 }),
},
y: 4.0,
z: "123".to_string(),
t: ("Hello".to_string(), 10),
btree_map_string: map.clone(),
btree_set_u64: set.clone(),
linked_list_string: vec!["a".to_string(), "b".to_string()].into_iter().collect(),
vec_deque_u64: vec![1, 2, 3].into_iter().collect(),
bytes: vec![5, 4, 3, 2, 1].into(),
bytes_mut: BytesMut::from(&[1, 2, 3, 4, 5][..]),
v: vec!["qwe".to_string(), "zxc".to_string()],
w: vec![0].into_boxed_slice(),
box_str: Box::from("asd"),
i: [4u8; 32],
u: Ok("Hello".to_string()),
lazy: Some(5),
c: borrow::Cow::Borrowed("Hello"),
cow_arr: borrow::Cow::Borrowed(&cow_arr),
range_u32: 12..71,
skipped: Some(6),
};
let encoded_a_len = to_vec(&a).unwrap().len();
let len_helper_result = borsh::object_length(&a).unwrap();
assert_eq!(encoded_a_len, len_helper_result);
}
@@ -0,0 +1,77 @@
#![allow(clippy::float_cmp)]
use borsh::{from_slice, to_vec};
#[cfg(feature = "derive")]
use borsh::{BorshDeserialize, BorshSerialize};
use alloc::string::{String, ToString};
macro_rules! test_array {
($v: expr, $t: ty, $len: expr) => {
let buf = borsh::to_vec(&$v).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(buf);
let actual_v: [$t; $len] = from_slice(&buf).expect("failed to deserialize");
assert_eq!($v.len(), actual_v.len());
#[allow(clippy::reversed_empty_ranges)]
for i in 0..$len {
assert_eq!($v[i], actual_v[i]);
}
};
}
macro_rules! test_arrays {
($test_name: ident, $el: expr, $t: ty) => {
#[test]
fn $test_name() {
test_array!([$el; 0], $t, 0);
test_array!([$el; 1], $t, 1);
test_array!([$el; 2], $t, 2);
test_array!([$el; 3], $t, 3);
test_array!([$el; 4], $t, 4);
test_array!([$el; 8], $t, 8);
test_array!([$el; 16], $t, 16);
test_array!([$el; 32], $t, 32);
test_array!([$el; 64], $t, 64);
test_array!([$el; 65], $t, 65);
}
};
}
test_arrays!(test_array_u8, 100u8, u8);
test_arrays!(test_array_i8, 100i8, i8);
test_arrays!(test_array_u32, 1000000000u32, u32);
test_arrays!(test_array_u64, 1000000000000000000u64, u64);
test_arrays!(
test_array_u128,
1000000000000000000000000000000000000u128,
u128
);
test_arrays!(test_array_f32, 1000000000.0f32, f32);
test_arrays!(test_array_array_u8, [100u8; 32], [u8; 32]);
test_arrays!(test_array_zst, (), ());
#[cfg(feature = "derive")]
#[derive(BorshDeserialize, BorshSerialize, PartialEq, Debug)]
struct CustomStruct(u8);
#[cfg(feature = "derive")]
#[test]
fn test_custom_struct_array() {
let arr = [CustomStruct(0), CustomStruct(1), CustomStruct(2)];
let serialized = to_vec(&arr).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(serialized);
let deserialized: [CustomStruct; 3] = from_slice(&serialized).unwrap();
assert_eq!(arr, deserialized);
}
#[test]
fn test_string_array() {
let arr = ["0".to_string(), "1".to_string(), "2".to_string()];
let serialized = to_vec(&arr).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(serialized);
let deserialized: [String; 3] = from_slice(&serialized).unwrap();
assert_eq!(arr, deserialized);
}
@@ -0,0 +1,53 @@
use borsh::{from_slice, to_vec};
use alloc::{
string::String,
vec::Vec,
};
/// Verifies serialisation and deserialisation of an ASCII string `value`.
fn check_ascii(value: &str) -> Vec<u8> {
// Caller promises value is ASCII.
let ascii_str = ascii::AsciiStr::from_ascii(&value).unwrap();
let buf = to_vec(ascii_str).unwrap();
// AsciiStr and AsciiString serialise the same way String does.
assert_eq!(buf, to_vec(&ascii::AsciiString::from(ascii_str)).unwrap());
// Check round trip.
let got = from_slice::<ascii::AsciiString>(&buf).unwrap();
assert_eq!(ascii_str, got);
buf
}
macro_rules! test_ascii_string {
($test_name: ident, $str: expr, $snap:expr) => {
#[test]
fn $test_name() {
let value = String::from($str);
let _buf = check_ascii(&value);
#[cfg(feature = "std")]
if $snap {
insta::assert_debug_snapshot!(_buf);
}
}
};
}
test_ascii_string!(test_empty_string, "", true);
test_ascii_string!(test_a, "a", true);
test_ascii_string!(test_hello_world, "hello world", true);
test_ascii_string!(test_x_1024, "x".repeat(1024), true);
test_ascii_string!(test_x_4096, "x".repeat(4096), false);
test_ascii_string!(test_x_65535, "x".repeat(65535), false);
test_ascii_string!(test_hello_10, "hello world!".repeat(30), true);
test_ascii_string!(test_hello_1000, "hello Achilles!".repeat(1000), false);
#[test]
fn test_ascii_char() {
use ascii::AsciiChar;
let buf = to_vec(&AsciiChar::Dot).unwrap();
assert_eq!(".".as_bytes(), buf);
assert_eq!(AsciiChar::Dot, from_slice::<AsciiChar>(&buf).unwrap());
from_slice::<AsciiChar>(&[b'\x80']).unwrap_err();
}
@@ -0,0 +1,94 @@
use alloc::{
collections::{BTreeMap, BTreeSet},
string::{String, ToString},
vec,
vec::Vec,
};
use borsh::{from_slice, BorshSerialize};
macro_rules! btreeset_test_template [
[$test_name: ident, $($key: expr),* ] => [
#[allow(unused_mut)]
#[allow(redundant_semicolons)]
#[test]
fn $test_name() {
let mut set = BTreeSet::new();
set_insert_deser_assert_macro!(set, data, $($key),*);
let actual_set = from_slice::<BTreeSet<String>>(&data).unwrap();
assert_eq!(set, actual_set);
}
]
];
macro_rules! btreemap_test_template [
[$test_name: ident, $($key: expr => $value: expr),* ] => [
#[allow(unused_mut)]
#[allow(redundant_semicolons)]
#[test]
fn $test_name() {
let mut map = BTreeMap::new();
map_insert_deser_assert_macro!(map, data, $($key => $value),*);
let actual_map = from_slice::<BTreeMap<String, String>>(&data).unwrap();
assert_eq!(map, actual_map);
}
]
];
btreeset_test_template!(test_empty_btreeset,);
btreeset_test_template!(test_1_element_btreeset, "one".to_string());
btreeset_test_template!(
test_2_element_btreeset,
"one".to_string(),
"different".to_string()
);
btreeset_test_template!(
test_default_btreeset,
"foo".to_string(),
"many".to_string(),
"various".to_string(),
"different".to_string(),
"keys".to_string(),
"one".to_string()
);
btreemap_test_template!(test_default_btreemap,
"foo".to_string() => "bar".to_string(),
"one".to_string() => "two".to_string()
);
btreemap_test_template!(test_empty_btreemap,);
btreemap_test_template!(test_1_element_btreemap,
"one".to_string() => "element".to_string()
);
btreemap_test_template!(test_8_element_btreemap,
"one".to_string() => "element".to_string(),
"key".to_string() => "powers".to_string(),
"more".to_string() => "of".to_string(),
"various".to_string() => "two".to_string(),
"different".to_string() => "are".to_string(),
"keys".to_string() => "always".to_string(),
"where".to_string() => "unpredictable".to_string(),
"nowhere".to_string() => "pile".to_string()
);
#[cfg(feature = "de_strict_order")]
const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order";
set_wrong_order_test!(test_btreeset_deser_err_wrong_order, BTreeSet<String>);
map_wrong_order_test!(test_btreemap_deser_err_wrong_order, BTreeMap<String, String>);
@@ -0,0 +1,23 @@
use alloc::string::{String, ToString};
#[test]
fn test_cell_roundtrip() {
let cell = core::cell::Cell::new(42u32);
let out = borsh::to_vec(&cell).unwrap();
let cell_round: core::cell::Cell<u32> = borsh::from_slice(&out).unwrap();
assert_eq!(cell, cell_round);
}
#[test]
fn test_ref_cell_roundtrip() {
let rcell = core::cell::RefCell::new("str".to_string());
let out = borsh::to_vec(&rcell).unwrap();
let rcell_round: core::cell::RefCell<String> = borsh::from_slice(&out).unwrap();
assert_eq!(rcell, rcell_round);
}
+71
View File
@@ -0,0 +1,71 @@
use borsh::{from_slice, to_vec};
use core::{matches, ops::Deref};
use alloc::string::ToString;
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"),
]
);
}
@@ -0,0 +1,213 @@
#[cfg(feature = "std")]
use core::hash::BuildHasher;
#[cfg(feature = "hashbrown")]
use hashbrown::{HashMap, HashSet};
#[cfg(feature = "std")]
use std::collections::{
hash_map::{DefaultHasher, RandomState},
HashMap, HashSet,
};
#[cfg(not(feature = "std"))]
use core::iter::IntoIterator;
use alloc::{
string::{String, ToString},
vec,
vec::Vec,
};
use borsh::{from_slice, BorshSerialize};
macro_rules! hashset_test_template [
[$test_name: ident, $($key: expr),* ] => [
#[allow(unused_mut)]
#[allow(redundant_semicolons)]
#[test]
fn $test_name() {
let mut set = HashSet::new();
set_insert_deser_assert_macro!(set, data, $($key),*);
let actual_set = from_slice::<HashSet<String>>(&data).unwrap();
assert_eq!(set, actual_set);
}
]
];
macro_rules! hashmap_test_template [
[$test_name: ident, $($key: expr => $value: expr),* ] => [
#[allow(unused_mut)]
#[allow(redundant_semicolons)]
#[test]
fn $test_name() {
let mut map = HashMap::new();
map_insert_deser_assert_macro!(map, data, $($key => $value),*);
let actual_map = from_slice::<HashMap<String, String>>(&data).unwrap();
assert_eq!(map, actual_map);
}
]
];
#[derive(Default)]
#[cfg(feature = "std")]
struct NewHasher(RandomState);
#[cfg(feature = "std")]
impl BuildHasher for NewHasher {
type Hasher = DefaultHasher;
fn build_hasher(&self) -> DefaultHasher {
self.0.build_hasher()
}
}
#[cfg(feature = "std")]
macro_rules! generic_hashset_test_template [
[$test_name: ident, $($key: expr),* ] => [
#[allow(unused_mut)]
#[allow(redundant_semicolons)]
#[test]
fn $test_name() {
let mut set = HashSet::with_hasher(NewHasher::default());
set_insert_deser_assert_macro!(set, data, $($key),*);
let actual_set = from_slice::<HashSet<String, NewHasher>>(&data).unwrap();
assert_eq!(set, actual_set);
}
]
];
#[cfg(feature = "std")]
macro_rules! generic_hashmap_test_template [
[$test_name: ident, $($key: expr => $value: expr),* ] => [
#[allow(unused_mut)]
#[allow(redundant_semicolons)]
#[test]
fn $test_name() {
let mut map = HashMap::with_hasher(NewHasher::default());
map_insert_deser_assert_macro!(map, data, $($key => $value),*);
let actual_map = from_slice::<HashMap<String, String, NewHasher>>(&data).unwrap();
assert_eq!(map, actual_map);
}
]
];
hashset_test_template!(test_empty_hashset,);
hashset_test_template!(test_1_element_hashset, "one".to_string());
hashset_test_template!(
test_2_element_hashset,
"one".to_string(),
"different".to_string()
);
hashset_test_template!(
test_default_hashset,
"foo".to_string(),
"many".to_string(),
"various".to_string(),
"different".to_string(),
"keys".to_string(),
"one".to_string()
);
#[cfg(feature = "std")]
generic_hashset_test_template!(test_empty_generic_hashset,);
#[cfg(feature = "std")]
generic_hashset_test_template!(test_1_element_generic_hashset, "one".to_string());
#[cfg(feature = "std")]
generic_hashset_test_template!(
test_2_element_generic_hashset,
"one".to_string(),
"different".to_string()
);
#[cfg(feature = "std")]
generic_hashset_test_template!(
test_generic_hashset,
"foo".to_string(),
"many".to_string(),
"various".to_string(),
"different".to_string(),
"keys".to_string(),
"one".to_string()
);
hashmap_test_template!(test_default_hashmap,
"foo".to_string() => "bar".to_string(),
"one".to_string() => "two".to_string()
);
hashmap_test_template!(test_empty_hashmap,);
hashmap_test_template!(test_1_element_hashmap,
"one".to_string() => "element".to_string()
);
hashmap_test_template!(test_8_element_hashmap,
"one".to_string() => "element".to_string(),
"key".to_string() => "powers".to_string(),
"more".to_string() => "of".to_string(),
"various".to_string() => "two".to_string(),
"different".to_string() => "are".to_string(),
"keys".to_string() => "always".to_string(),
"where".to_string() => "unpredictable".to_string(),
"nowhere".to_string() => "pile".to_string()
);
#[cfg(feature = "std")]
generic_hashmap_test_template!(test_generic_hash_hashmap,
"foo".to_string() => "bar".to_string(),
"one".to_string() => "two".to_string()
);
#[cfg(feature = "std")]
generic_hashmap_test_template!(test_empty_generic_hashmap,);
#[cfg(feature = "std")]
generic_hashmap_test_template!(test_1_element_generic_hashmap,
"one".to_string() => "element".to_string()
);
#[cfg(feature = "std")]
generic_hashmap_test_template!(test_8_element_generic_hashmap,
"one".to_string() => "element".to_string(),
"key".to_string() => "powers".to_string(),
"more".to_string() => "of".to_string(),
"various".to_string() => "two".to_string(),
"different".to_string() => "are".to_string(),
"keys".to_string() => "always".to_string(),
"where".to_string() => "unpredictable".to_string(),
"nowhere".to_string() => "pile".to_string()
);
#[cfg(feature = "de_strict_order")]
const ERROR_WRONG_ORDER_OF_KEYS: &str = "keys were not serialized in ascending order";
set_wrong_order_test!(test_hashset_deser_err_wrong_order, HashSet<String>);
#[cfg(feature = "std")]
set_wrong_order_test!(test_generic_hashset_deser_err_wrong_order, HashSet<String, NewHasher>);
map_wrong_order_test!(test_hashmap_deser_err_wrong_order, HashMap<String, String>);
#[cfg(feature = "std")]
map_wrong_order_test!(test_generic_hashmap_deser_err_wrong_order, HashMap<String, String, NewHasher>);
@@ -0,0 +1,41 @@
use borsh::BorshDeserialize;
use indexmap::{IndexMap, IndexSet};
#[test]
// Taken from https://github.com/indexmap-rs/indexmap/blob/dd06e5773e4f91748396c67d00c83637f5c0dd49/src/borsh.rs#L100
// license: MIT OR Apache-2.0
fn test_indexmap_roundtrip() {
let original_map: IndexMap<i32, i32> = {
let mut map = IndexMap::new();
map.insert(1, 2);
map.insert(3, 4);
map.insert(5, 6);
map
};
let serialized_map = borsh::to_vec(&original_map).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(serialized_map);
let deserialized_map: IndexMap<i32, i32> =
BorshDeserialize::try_from_slice(&serialized_map).unwrap();
assert_eq!(original_map, deserialized_map);
}
#[test]
// Taken from https://github.com/indexmap-rs/indexmap/blob/dd06e5773e4f91748396c67d00c83637f5c0dd49/src/borsh.rs#L115
// license: MIT OR Apache-2.0
fn test_indexset_roundtrip() {
let mut original_set = IndexSet::new();
[1, 2, 3, 4, 5, 6].iter().for_each(|&i| {
original_set.insert(i);
});
let serialized_set = borsh::to_vec(&original_set).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(serialized_set);
let deserialized_set: IndexSet<i32> =
BorshDeserialize::try_from_slice(&serialized_set).unwrap();
assert_eq!(original_set, deserialized_set);
}
@@ -0,0 +1,56 @@
use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use alloc::{vec, vec::Vec};
#[test]
fn test_ipv4_addr_roundtrip_enum() {
let original = IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1));
let encoded = borsh::to_vec(&original).expect("Serialization failed");
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);
let decoded = borsh::from_slice::<IpAddr>(&encoded).expect("Deserialization failed");
assert_eq!(original, decoded);
}
#[test]
fn test_ipv4_addr_roundtrip() {
let original = Ipv4Addr::new(192, 168, 0, 1);
let encoded = borsh::to_vec(&original).expect("Serialization failed");
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);
let decoded = borsh::from_slice::<Ipv4Addr>(&encoded).expect("Deserialization failed");
assert_eq!(original, decoded);
}
#[test]
fn test_ipv6_addr_roundtrip_enum() {
let original = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
let encoded = borsh::to_vec(&original).expect("Serialization failed");
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);
let decoded = borsh::from_slice::<IpAddr>(&encoded).expect("Deserialization failed");
assert_eq!(original, decoded);
}
#[test]
fn test_ipv6_addr_roundtrip() {
let original = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
let encoded = borsh::to_vec(&original).expect("Serialization failed");
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);
let decoded = borsh::from_slice::<Ipv6Addr>(&encoded).expect("Deserialization failed");
assert_eq!(original, decoded);
}
#[test]
fn test_ipaddr_vec_roundtrip() {
let original = vec![
IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)),
IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)),
IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)),
];
let encoded = borsh::to_vec(&original).expect("Serialization failed");
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);
let decoded = borsh::from_slice::<Vec<IpAddr>>(&encoded).expect("Deserialization failed");
assert_eq!(original, decoded);
}
@@ -0,0 +1,32 @@
use borsh::from_slice;
use core::num::*;
#[test]
fn test_nonzero_integer_u8() {
let bytes = &[1];
assert_eq!(from_slice::<NonZeroU8>(bytes).unwrap().get(), 1);
}
#[test]
fn test_nonzero_integer_u32() {
let bytes = &[255, 0, 0, 0];
assert_eq!(from_slice::<NonZeroU32>(bytes).unwrap().get(), 255);
}
#[test]
fn test_nonzero_integer_usize() {
let bytes = &[1, 1, 0, 0, 0, 0, 0, 0];
assert_eq!(from_slice::<NonZeroUsize>(bytes).unwrap().get(), 257);
}
#[test]
fn test_nonzero_integer_i64() {
let bytes = &[255; 8];
assert_eq!(from_slice::<NonZeroI64>(bytes).unwrap().get(), -1);
}
#[test]
fn test_nonzero_integer_i16b() {
let bytes = &[0, 0b1000_0000];
assert_eq!(from_slice::<NonZeroI16>(bytes).unwrap().get(), i16::MIN);
}
@@ -0,0 +1,25 @@
use borsh::{from_slice, to_vec};
macro_rules! test_primitive {
($test_name: ident, $v: expr, $t: ty) => {
#[test]
fn $test_name() {
let expected: $t = $v;
let buf = to_vec(&expected).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(buf);
let actual = from_slice::<$t>(&buf).expect("failed to deserialize");
assert_eq!(actual, expected);
}
};
}
test_primitive!(test_isize_neg, -100isize, isize);
test_primitive!(test_isize_pos, 100isize, isize);
test_primitive!(test_isize_min, isize::min_value(), isize);
test_primitive!(test_isize_max, isize::max_value(), isize);
test_primitive!(test_usize, 100usize, usize);
test_primitive!(test_usize_min, usize::min_value(), usize);
test_primitive!(test_usize_max, usize::max_value(), usize);
@@ -0,0 +1,11 @@
#[test]
fn test_ranges() {
let want = (1..2, 3..=4, 5.., ..6, ..=7, ..);
let encoded = borsh::to_vec(&want).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(encoded);
let got = borsh::from_slice(&encoded).unwrap();
assert_eq!(want, got);
}
+37
View File
@@ -0,0 +1,37 @@
pub use alloc::{rc, sync};
use borsh::{from_slice, to_vec};
#[test]
fn test_rc_roundtrip() {
let value = rc::Rc::new(8u8);
let serialized = to_vec(&value).unwrap();
let deserialized = from_slice::<rc::Rc<u8>>(&serialized).unwrap();
assert_eq!(value, deserialized);
}
#[test]
fn test_slice_rc() {
let original: &[i32] = &[1, 2, 3, 4, 6, 9, 10];
let shared: rc::Rc<[i32]> = rc::Rc::from(original);
let serialized = to_vec(&shared).unwrap();
let deserialized = from_slice::<rc::Rc<[i32]>>(&serialized).unwrap();
assert_eq!(original, &*deserialized);
}
#[test]
fn test_arc_roundtrip() {
let value = sync::Arc::new(8u8);
let serialized = to_vec(&value).unwrap();
let deserialized = from_slice::<sync::Arc<u8>>(&serialized).unwrap();
assert_eq!(value, deserialized);
}
#[test]
fn test_slice_arc() {
let original: &[i32] = &[1, 2, 3, 4, 6, 9, 10];
let shared: sync::Arc<[i32]> = sync::Arc::from(original);
let serialized = to_vec(&shared).unwrap();
let deserialized = from_slice::<sync::Arc<[i32]>>(&serialized).unwrap();
assert_eq!(original, &*deserialized);
}
@@ -0,0 +1,40 @@
use alloc::string::String;
use borsh::{from_slice, to_vec};
/// Verifies serialisation and deserialisation of the given string.
///
/// Returns serialised representation of the string.
fn check_string(value: &str) -> alloc::vec::Vec<u8> {
// Encoding is the same as Vec<u8> with UTF-8 encoded string.
let buf = to_vec(value.as_bytes()).unwrap();
assert_eq!(buf, to_vec(value).unwrap());
assert_eq!(buf, to_vec(&String::from(value)).unwrap());
// Check round trip.
assert_eq!(value, from_slice::<String>(&buf).unwrap());
buf
}
macro_rules! test_string {
($test_name: ident, $str: expr, $snap:expr) => {
#[test]
fn $test_name() {
let value = String::from($str);
let _buf = check_string(&value);
#[cfg(feature = "std")]
if $snap {
insta::assert_debug_snapshot!(_buf);
}
}
};
}
test_string!(test_empty_string, "", true);
test_string!(test_a, "a", true);
test_string!(test_hello_world, "hello world", true);
test_string!(test_x_1024, "x".repeat(1024), true);
test_string!(test_x_4096, "x".repeat(4096), false);
test_string!(test_x_65535, "x".repeat(65535), false);
test_string!(test_hello_10, "hello world!".repeat(30), true);
test_string!(test_hello_1000, "hello world!".repeat(1000), false);
test_string!(test_non_ascii, "💩", true);
@@ -0,0 +1,11 @@
use borsh::{from_slice, to_vec};
#[test]
fn test_unary_tuple() {
let expected = (true,);
let buf = to_vec(&expected).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(buf);
let actual = from_slice::<(bool,)>(&buf).expect("failed to deserialize");
assert_eq!(actual, expected);
}
+17
View File
@@ -0,0 +1,17 @@
use borsh::BorshDeserialize;
use uuid::Uuid;
#[test]
fn test_uuid_roundtrip() {
let original_uuid = Uuid::from_bytes([
0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
0xd7, 0xd8,
]);
let serialized_uuid = borsh::to_vec(&original_uuid).unwrap();
#[cfg(feature = "std")]
insta::assert_debug_snapshot!(serialized_uuid);
let deserialized_uuid: Uuid =
BorshDeserialize::try_from_slice(&serialized_uuid).unwrap();
assert_eq!(original_uuid, deserialized_uuid);
}
+41
View File
@@ -0,0 +1,41 @@
use borsh::{from_slice, to_vec};
use alloc::{
string::{String, ToString},
vec,
vec::Vec,
};
macro_rules! test_vec {
($v: expr, $t: ty, $snap: expr) => {
let buf = to_vec(&$v).unwrap();
#[cfg(feature = "std")]
if $snap {
insta::assert_debug_snapshot!(buf);
}
let actual_v: Vec<$t> = from_slice(&buf).expect("failed to deserialize");
assert_eq!(actual_v, $v);
};
}
macro_rules! test_vecs {
($test_name: ident, $el: expr, $t: ty) => {
#[test]
fn $test_name() {
test_vec!(Vec::<$t>::new(), $t, true);
test_vec!(vec![$el], $t, true);
test_vec!(vec![$el; 10], $t, true);
test_vec!(vec![$el; 100], $t, true);
test_vec!(vec![$el; 1000], $t, false); // one assumes that the concept has been proved
test_vec!(vec![$el; 10000], $t, false);
}
};
}
test_vecs!(test_vec_u8, 100u8, u8);
test_vecs!(test_vec_i8, 100i8, i8);
test_vecs!(test_vec_u32, 1000000000u32, u32);
test_vecs!(test_vec_f32, 1000000000.0f32, f32);
test_vecs!(test_vec_string, "a".to_string(), String);
test_vecs!(test_vec_vec_u8, vec![100u8; 10], Vec<u8>);
test_vecs!(test_vec_vec_u32, vec![100u32; 10], Vec<u32>);