use crate::common_macro::schema_imports::*; #[track_caller] fn test_ok(want: usize) { let schema = BorshSchemaContainer::for_type::(); assert_eq!(Ok(want), schema.max_serialized_size()); } #[track_caller] fn test_err(err: SchemaMaxSerializedSizeError) { let schema = BorshSchemaContainer::for_type::(); assert_eq!(Err(err), schema.max_serialized_size()); } const MAX_LEN: usize = u32::MAX as usize; #[test] fn max_serialized_size_primitives() { test_ok::<()>(0); test_ok::(1); test_ok::(4); test_ok::(8); test_ok::(1); test_ok::(2); test_ok::(4); test_ok::(8); test_ok::(16); test_ok::(1); test_ok::(2); test_ok::(4); test_ok::(8); test_ok::(16); test_ok::(1); test_ok::(2); test_ok::(4); test_ok::(8); test_ok::(16); test_ok::(1); test_ok::(2); test_ok::(4); test_ok::(8); test_ok::(16); test_ok::(8); test_ok::(8); test_ok::(8); } #[test] fn max_serialized_size_built_in_types() { test_ok::(0); test_ok::>(2); test_ok::>(8); test_ok::>(1); test_ok::>(2); test_ok::>(9); test_ok::>>(1 + 4 + MAX_LEN); test_ok::<()>(0); test_ok::<(u8,)>(1); test_ok::<(u8, u32)>(5); test_ok::<[u8; 0]>(0); test_ok::<[u8; 16]>(16); test_ok::<[[u8; 4]; 4]>(16); test_ok::<[u16; 0]>(0); test_ok::<[u16; 16]>(32); test_ok::<[[u16; 4]; 4]>(32); test_ok::>(4 + MAX_LEN); test_ok::(4 + MAX_LEN); test_err::>>(SchemaMaxSerializedSizeError::Overflow); test_ok::>>(4 + MAX_LEN * 4); test_ok::<[[[(); MAX_LEN]; MAX_LEN]; MAX_LEN]>(0); } #[test] fn max_serialized_size_derived_types() { #[derive(BorshSchema)] pub struct Empty; #[derive(BorshSchema)] pub struct Named { _foo: usize, _bar: [u8; 15], } #[derive(BorshSchema)] #[allow(unused)] pub struct Unnamed(usize, [u8; 15]); #[derive(BorshSchema)] struct Multiple { _usz0: usize, _usz1: usize, _usz2: usize, _vec0: Vec, _vec1: Vec, } #[derive(BorshSchema)] #[allow(unused)] struct Recursive(Option>); test_ok::(0); test_ok::(23); test_ok::(23); test_ok::(3 * 8 + 2 * (4 + MAX_LEN * 8)); test_err::(SchemaMaxSerializedSizeError::Overflow); test_err::(SchemaMaxSerializedSizeError::Recursive); } #[test] fn max_serialized_size_custom_enum() { #[allow(dead_code)] enum Maybe { Just(T), Nothing, } impl BorshSchema for Maybe { fn declaration() -> Declaration { let res = format!(r#"Maybe<{}, {}>"#, N, T::declaration()); res } fn add_definitions_recursively(definitions: &mut BTreeMap) { let definition = Definition::Enum { tag_width: N, variants: vec![ (0, "Just".into(), T::declaration()), (1, "Nothing".into(), <()>::declaration()), ], }; add_definition(Self::declaration(), definition, definitions); T::add_definitions_recursively(definitions); <()>::add_definitions_recursively(definitions); } } test_ok::>(0); test_ok::>(2); test_ok::>(8); test_ok::>(1); test_ok::>(3); test_ok::>(9); test_ok::>(4); test_ok::>(6); test_ok::>(12); } #[test] fn max_serialized_size_bound_vec() { #[allow(dead_code)] struct BoundVec; impl BorshSchema for BoundVec { fn declaration() -> Declaration { format!("BoundVec<{}, {}>", W, N) } fn add_definitions_recursively(definitions: &mut BTreeMap) { let definition = Definition::Sequence { length_width: W, length_range: 0..=N, elements: "u8".to_string(), }; add_definition(Self::declaration(), definition, definitions); u8::add_definitions_recursively(definitions); } } test_ok::>(4); test_ok::>(4 + u16::MAX as usize); test_ok::>(24); test_ok::>(1); test_ok::>(1 + u16::MAX as usize); test_ok::>(21); test_ok::>(0); test_ok::>(u16::MAX as usize); test_ok::>(20); } #[test] fn max_serialized_size_small_vec() { #[allow(dead_code)] struct SmallVec(core::marker::PhantomData); impl BorshSchema for SmallVec { fn declaration() -> Declaration { format!(r#"SmallVec<{}>"#, T::declaration()) } fn add_definitions_recursively(definitions: &mut BTreeMap) { let definition = Definition::Sequence { length_width: 1, length_range: 0..=u8::MAX as u64, elements: T::declaration(), }; add_definition(Self::declaration(), definition, definitions); T::add_definitions_recursively(definitions); } } test_ok::>(u8::MAX as usize + 1); test_ok::>(u8::MAX as usize * 2 + 1); }