Skip to content

Commit 4acaec2

Browse files
schema changes
1 parent 3da00ce commit 4acaec2

13 files changed

+147
-6
lines changed

borsh-derive/src/internals/enum_discriminant.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub struct Discriminants{
1010
variants: HashMap<Ident, TokenStream>,
1111
discriminant_type : syn::TypePath,
1212
use_discriminant: bool,
13+
tag_width: u8,
1314
}
1415

1516
impl Discriminants {
@@ -35,8 +36,10 @@ impl Discriminants {
3536
}
3637

3738
let mut discriminant_type: TypePath = syn::parse_str("u8").unwrap();
39+
let mut tag_width = 1;
3840

39-
if let Some((tag_width, span)) = maybe_borsh_tag_width {
41+
if let Some((defined_tag_width, span)) = maybe_borsh_tag_width {
42+
tag_width = defined_tag_width;
4043
if !use_discriminant {
4144
return Err(syn::Error::new(
4245
span,
@@ -67,7 +70,6 @@ impl Discriminants {
6770
)),
6871
};
6972
discriminant_type = rust_repr.clone();
70-
println!("repr_type: {:?}, repr_size: {:?} tag_width:{:?} ", repr_type, repr_size, tag_width);
7173

7274
if repr_size != tag_width {
7375
return Err(syn::Error::new(
@@ -83,20 +85,24 @@ impl Discriminants {
8385
));
8486
}
8587
}
86-
println!("discriminant_type: {:?}", discriminant_type.path.get_ident());
8788
}
8889

8990
Ok(Self {
9091
variants : map,
9192
discriminant_type,
92-
use_discriminant
93+
use_discriminant,
94+
tag_width,
9395
})
9496
}
9597

9698
pub fn discriminant_type(&self) -> &syn::TypePath {
9799
&self.discriminant_type
98100
}
99101

102+
pub fn tag_width(&self) -> u8 {
103+
self.tag_width
104+
}
105+
100106
pub fn get(
101107
&self,
102108
variant_ident: &Ident,

borsh-derive/src/internals/schema/enums/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,15 @@ pub fn process(input: &ItemEnum, cratename: Path) -> syn::Result<TokenStream2> {
6363
variants_defs.push(variant_output.variant_entry);
6464
}
6565

66+
let tag_width = discriminants.tag_width();
6667
let type_definitions = quote! {
6768
fn add_definitions_recursively(definitions: &mut #cratename::__private::maybestd::collections::BTreeMap<#cratename::schema::Declaration, #cratename::schema::Definition>) {
6869
#inner_defs
6970
#add_recursive_defs
7071
let definition = #cratename::schema::Definition::Enum {
71-
tag_width: 1,
72+
tag_width: #tag_width,
7273
variants: #cratename::__private::maybestd::vec![#(#variants_defs),*],
74+
tag_signed: false,
7375
};
7476
#cratename::schema::add_definition(<Self as #cratename::BorshSchema>::declaration(), definition, definitions);
7577
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
source: borsh-derive/src/internals/schema/enums/mod.rs
3+
assertion_line: 403
4+
expression: pretty_print_syn_str(&actual).unwrap()
5+
---
6+
impl<K: Key, V> borsh::BorshSchema for A<K, V>
7+
where
8+
V: Value,
9+
K: borsh::BorshSchema,
10+
V: borsh::BorshSchema,
11+
{
12+
fn declaration() -> borsh::schema::Declaration {
13+
let params = borsh::__private::maybestd::vec![
14+
< K as borsh::BorshSchema > ::declaration(), < V as borsh::BorshSchema >
15+
::declaration()
16+
];
17+
format!(r#"{}<{}>"#, "A", params.join(", "))
18+
}
19+
fn add_definitions_recursively(
20+
definitions: &mut borsh::__private::maybestd::collections::BTreeMap<
21+
borsh::schema::Declaration,
22+
borsh::schema::Definition,
23+
>,
24+
) {
25+
#[allow(dead_code)]
26+
#[derive(borsh::BorshSchema)]
27+
#[borsh(crate = "borsh")]
28+
struct AB<K: Key, V>
29+
where
30+
V: Value,
31+
{
32+
x: HashMap<K, V>,
33+
y: String,
34+
}
35+
#[allow(dead_code)]
36+
#[derive(borsh::BorshSchema)]
37+
#[borsh(crate = "borsh")]
38+
struct AC<K: Key>(K, Vec<A>);
39+
<AB<K, V> as borsh::BorshSchema>::add_definitions_recursively(definitions);
40+
<AC<K> as borsh::BorshSchema>::add_definitions_recursively(definitions);
41+
let definition = borsh::schema::Definition::Enum {
42+
tag_width: 1u8,
43+
variants: borsh::__private::maybestd::vec![
44+
(u8::from(0u8) as i64, "B".into(), < AB < K, V > as borsh::BorshSchema >
45+
::declaration()), (u8::from(1u8) as i64, "C".into(), < AC < K > as
46+
borsh::BorshSchema > ::declaration())
47+
],
48+
tag_signed: false,
49+
};
50+
borsh::schema::add_definition(
51+
<Self as borsh::BorshSchema>::declaration(),
52+
definition,
53+
definitions,
54+
);
55+
}
56+
}

borsh/src/schema.rs

+6
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ pub enum Definition {
112112
/// invalid if the value is greater than eight.
113113
tag_width: u8,
114114

115+
/// If true, than tag is signed value.
116+
/// If false, unsigned value.
117+
tag_signed: bool,
118+
115119
/// Possible variants of the enumeration.
116120
/// `VariantName` is metadata, not present in a type's serialized representation.
117121
variants: Vec<(DiscriminantValue, VariantName, Declaration)>,
@@ -601,6 +605,7 @@ where
601605
(0u8 as i64, "None".to_string(), <()>::declaration()),
602606
(1u8 as i64, "Some".to_string(), T::declaration()),
603607
],
608+
tag_signed: false,
604609
};
605610
add_definition(Self::declaration(), definition, definitions);
606611
T::add_definitions_recursively(definitions);
@@ -624,6 +629,7 @@ where
624629
(1u8 as i64, "Ok".to_string(), T::declaration()),
625630
(0u8 as i64, "Err".to_string(), E::declaration()),
626631
],
632+
tag_signed: false,
627633
};
628634
add_definition(Self::declaration(), definition, definitions);
629635
T::add_definitions_recursively(definitions);

borsh/src/schema/container_ext/max_size.rs

+2
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ fn max_serialized_size_impl<'a>(
126126
Ok(Definition::Enum {
127127
tag_width,
128128
variants,
129+
tag_signed: _,
129130
}) => {
130131
let mut max = 0;
131132
for (_, _, variant) in variants {
@@ -232,6 +233,7 @@ fn is_zero_size_impl<'a>(
232233
Ok(Definition::Enum {
233234
tag_width: 0,
234235
variants,
236+
tag_signed: _,
235237
}) => all(
236238
variants.iter(),
237239
|(_variant_discrim, _variant_name, declaration)| declaration,

borsh/src/schema/container_ext/validate.rs

+2
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,12 @@ fn validate_impl<'a>(
106106
Definition::Enum {
107107
tag_width,
108108
variants,
109+
tag_signed: _,
109110
} => {
110111
if *tag_width > U64_LEN {
111112
return Err(Error::TagTooWide(declaration.to_string()));
112113
}
114+
113115
for (_, _, variant) in variants {
114116
validate_impl(variant, schema, stack)?;
115117
}

borsh/tests/schema/container_extension/test_max_size.rs

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ fn max_serialized_size_custom_enum() {
133133
}
134134
fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
135135
let definition = Definition::Enum {
136+
tag_signed: false,
136137
tag_width: N,
137138
variants: vec![
138139
(0, "Just".into(), T::declaration()),

borsh/tests/schema/test_enum_discriminants.rs

+53-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ fn test_schema_discriminant_no_unit_type() {
2121
assert_eq!(
2222
schema_map! {
2323
"XY" => Definition::Enum {
24+
tag_signed: false,
2425
tag_width: 1,
2526
variants: vec![
2627
(0, "A".to_string(), "XYA".to_string()),
@@ -29,7 +30,7 @@ fn test_schema_discriminant_no_unit_type() {
2930
(22, "D".to_string(), "XYD".to_string()),
3031
(10, "E".to_string(), "XYE".to_string()),
3132
(11, "F".to_string(), "XYF".to_string())
32-
]
33+
],
3334
},
3435
"XYA" => Definition::Struct{ fields: Fields::Empty },
3536
"XYB" => Definition::Struct{ fields: Fields::Empty },
@@ -73,6 +74,7 @@ fn test_schema_discriminant_no_unit_type_no_use_discriminant() {
7374
assert_eq!(
7475
schema_map! {
7576
"XYNoDiscriminant" => Definition::Enum {
77+
tag_signed: false,
7678
tag_width: 1,
7779
variants: vec![
7880
(0, "A".to_string(), "XYNoDiscriminantA".to_string()),
@@ -100,3 +102,53 @@ fn test_schema_discriminant_no_unit_type_no_use_discriminant() {
100102
defs
101103
);
102104
}
105+
106+
107+
#[test]
108+
fn tag_widths() {
109+
#[derive(BorshSchema)]
110+
#[borsh(use_discriminant=true, tag_width = 2)]
111+
#[repr(u16)]
112+
enum U16Discriminant {
113+
A = 42u16,
114+
}
115+
116+
let mut defs = Default::default();
117+
U16Discriminant::add_definitions_recursively(&mut defs);
118+
assert_eq!(
119+
schema_map! {
120+
"U16Discriminant" => Definition::Enum {
121+
tag_signed: false,
122+
tag_width: 2,
123+
variants: vec![
124+
(42, "A".to_string(), "U16DiscriminantA".to_string()),
125+
],
126+
},
127+
"U16DiscriminantA" => Definition::Struct{ fields: Fields::Empty }
128+
},
129+
defs
130+
);
131+
132+
#[derive(BorshSchema)]
133+
#[borsh(use_discriminant = true, tag_width = 4)]
134+
#[repr(u32)]
135+
enum U32Discriminant {
136+
A = 42u32,
137+
}
138+
139+
let mut defs = Default::default();
140+
U32Discriminant::add_definitions_recursively(&mut defs);
141+
assert_eq!(
142+
schema_map! {
143+
"U32Discriminant" => Definition::Enum {
144+
tag_signed: false,
145+
tag_width: 4,
146+
variants: vec![
147+
(42, "A".to_string(), "U32DiscriminantA".to_string()),
148+
],
149+
},
150+
"U32DiscriminantA" => Definition::Struct{ fields: Fields::Empty }
151+
},
152+
defs
153+
);
154+
}

borsh/tests/schema/test_generic_enums.rs

+6
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub fn complex_enum_generics() {
4040
"ABacon" => Definition::Struct {fields: Fields::Empty},
4141
"Oil" => Definition::Struct {fields: Fields::Empty},
4242
"A<Cucumber, Wrapper>" => Definition::Enum {
43+
tag_signed: false,
4344
tag_width: 1,
4445
variants: vec![
4546
(0, "Bacon".to_string(), "ABacon".to_string()),
@@ -102,6 +103,7 @@ pub fn complex_enum_generics2() {
102103
assert_eq!(
103104
schema_map! {
104105
"A<Cucumber, Wrapper<String>>" => Definition::Enum {
106+
tag_signed: false,
105107
tag_width: 1,
106108
variants: vec![
107109
(0, "Bacon".to_string(), "ABacon".to_string()),
@@ -111,6 +113,7 @@ pub fn complex_enum_generics2() {
111113
]
112114
},
113115
"A<String, String>" => Definition::Enum {
116+
tag_signed: false,
114117
tag_width: 1,
115118
variants: vec![
116119
(0, "Bacon".to_string(), "ABacon".to_string()),
@@ -134,13 +137,15 @@ pub fn complex_enum_generics2() {
134137
},
135138
"Oil<u64, String>" => Definition::Struct { fields: Fields::NamedFields(vec![("seeds".to_string(), "HashMap<u64, String>".to_string()), ("liquid".to_string(), "Option<u64>".to_string())])},
136139
"Option<String>" => Definition::Enum {
140+
tag_signed: false,
137141
tag_width: 1,
138142
variants: vec![
139143
(0, "None".to_string(), "()".to_string()),
140144
(1, "Some".to_string(), "String".to_string())
141145
]
142146
},
143147
"Option<u64>" => Definition::Enum {
148+
tag_signed: false,
144149
tag_width: 1,
145150
variants: vec![
146151
(0, "None".to_string(), "()".to_string()),
@@ -166,6 +171,7 @@ pub fn complex_enum_generics2() {
166171
fn common_map_associated() -> BTreeMap<String, Definition> {
167172
schema_map! {
168173
"EnumParametrized<String, u32, i8, u16>" => Definition::Enum {
174+
tag_signed: false,
169175
tag_width: 1,
170176
variants: vec![
171177
(0, "B".to_string(), "EnumParametrizedB<u32, i8, u16>".to_string()),

borsh/tests/schema/test_option.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn simple_option() {
99
assert_eq!(
1010
schema_map! {
1111
"Option<u64>" => Definition::Enum {
12+
tag_signed: false,
1213
tag_width: 1,
1314
variants: vec![
1415
(0, "None".to_string(), "()".to_string()),
@@ -31,13 +32,15 @@ fn nested_option() {
3132
assert_eq!(
3233
schema_map! {
3334
"Option<u64>" => Definition::Enum {
35+
tag_signed: false,
3436
tag_width: 1,
3537
variants: vec![
3638
(0, "None".to_string(), "()".to_string()),
3739
(1, "Some".to_string(), "u64".to_string()),
3840
]
3941
},
4042
"Option<Option<u64>>" => Definition::Enum {
43+
tag_signed: false,
4144
tag_width: 1,
4245
variants: vec![
4346
(0, "None".to_string(), "()".to_string()),

borsh/tests/schema/test_recursive_enums.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub fn recursive_enum_schema() {
1414
assert_eq!(
1515
schema_map! {
1616
"ERecD" => Definition::Enum {
17+
tag_signed: false,
1718
tag_width: 1,
1819
variants: vec![
1920
(0, "B".to_string(), "ERecDB".to_string()),

borsh/tests/schema/test_schema_with_third_party.rs

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ pub fn enum_overriden() {
100100
assert_eq!(
101101
schema_map! {
102102
"C<u64, String>" => Definition::Enum {
103+
tag_signed: false,
103104
tag_width: 1,
104105
variants: vec![
105106
(0, "C3".to_string(), "CC3".to_string()),

borsh/tests/schema/test_simple_enums.rs

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub fn simple_enum() {
2525
"ABacon" => Definition::Struct{ fields: Fields::Empty },
2626
"AEggs" => Definition::Struct{ fields: Fields::Empty },
2727
"A" => Definition::Enum {
28+
tag_signed: false,
2829
tag_width: 1,
2930
variants: vec![(0, "Bacon".to_string(), "ABacon".to_string()), (1, "Eggs".to_string(), "AEggs".to_string())]
3031
}
@@ -47,6 +48,7 @@ pub fn single_field_enum() {
4748
schema_map! {
4849
"ABacon" => Definition::Struct {fields: Fields::Empty},
4950
"A" => Definition::Enum {
51+
tag_signed: false,
5052
tag_width: 1,
5153
variants: vec![(0, "Bacon".to_string(), "ABacon".to_string())]
5254
}
@@ -131,6 +133,7 @@ pub fn complex_enum_with_schema() {
131133
"ABacon" => Definition::Struct {fields: Fields::Empty},
132134
"Oil" => Definition::Struct {fields: Fields::Empty},
133135
"A" => Definition::Enum {
136+
tag_signed: false,
134137
tag_width: 1,
135138
variants: vec![
136139
(0, "Bacon".to_string(), "ABacon".to_string()),

0 commit comments

Comments
 (0)