From 2a13d3a29d43d86fa5061f199b2104fea5540e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dj8yf0=CE=BCl?= <26653921+dj8yfo@users.noreply.github.com> Date: Tue, 26 Sep 2023 20:12:55 +0300 Subject: [PATCH] feat!: add `DiscriminantValue` to `Definition::Enum::variants` tuples (#232) * feat!: add `DiscriminantValue` to `Definition::Enum::variants` tuples * test: add a couple of tests for enum with discriminants set schema * chore: restrict valid discriminants to be of `u8` range to be more congruent with `BorshSerialize`, `BorshDeserialize` * doc: mention `use_discriminant = ` in `BorshSchema` context --- .../src/internals/schema/enums/mod.rs | 89 +++++++++++- .../snapshots/borsh_discriminant_false.snap | 65 +++++++++ .../snapshots/borsh_discriminant_true.snap | 65 +++++++++ .../schema/enums/snapshots/complex_enum.snap | 12 +- .../snapshots/complex_enum_generics.snap | 13 +- ..._enum_generics_borsh_skip_named_field.snap | 13 +- ..._enum_generics_borsh_skip_tuple_field.snap | 13 +- .../enums/snapshots/filter_foreign_attrs.snap | 7 +- .../snapshots/generic_associated_type.snap | 7 +- ...eneric_associated_type_param_override.snap | 7 +- .../enums/snapshots/recursive_enum.snap | 7 +- .../schema/enums/snapshots/simple_enum.snap | 6 +- .../simple_enum_with_custom_crate.snap | 6 +- .../enums/snapshots/single_field_enum.snap | 3 +- .../snapshots/trailing_comma_generics.snap | 7 +- .../enums/snapshots/with_funcs_attr.snap | 7 +- borsh-derive/src/lib.rs | 68 ++++++++- borsh/src/schema.rs | 24 ++-- borsh/src/schema/container_ext/max_size.rs | 8 +- borsh/src/schema/container_ext/validate.rs | 2 +- ...chema_enums__complex_enum_with_schema.snap | 32 +++++ borsh/tests/test_enum_discriminants.rs | 129 ++++++++++++++++++ borsh/tests/test_schema_enums.rs | 24 ++-- borsh/tests/test_schema_nested.rs | 24 ++-- borsh/tests/test_schema_recursive.rs | 4 +- borsh/tests/test_schema_with.rs | 4 +- 26 files changed, 563 insertions(+), 83 deletions(-) create mode 100644 borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_false.snap create mode 100644 borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_true.snap diff --git a/borsh-derive/src/internals/schema/enums/mod.rs b/borsh-derive/src/internals/schema/enums/mod.rs index 17a84241a..a6fca9ddc 100644 --- a/borsh-derive/src/internals/schema/enums/mod.rs +++ b/borsh-derive/src/internals/schema/enums/mod.rs @@ -3,7 +3,11 @@ use quote::{quote, ToTokens}; use std::collections::HashSet; use syn::{Fields, Generics, Ident, ItemEnum, ItemStruct, Path, Variant, Visibility}; -use crate::internals::{attributes::field, generics, schema}; +use crate::internals::{ + attributes::{field, item}, + enum_discriminant::Discriminants, + generics, schema, +}; fn transform_variant_fields(mut input: Fields) -> Fields { match input { @@ -31,14 +35,23 @@ pub fn process(input: &ItemEnum, cratename: Path) -> syn::Result { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let mut where_clause = generics::default_where(where_clause); let mut generics_output = schema::GenericsOutput::new(&generics); + let use_discriminant = item::contains_use_discriminant(input)?; + let discriminants = Discriminants::new(&input.variants); // Generate functions that return the schema for variants. + let mut discriminant_variables = vec![]; let mut variants_defs = vec![]; let mut inner_defs = TokenStream2::new(); let mut add_recursive_defs = TokenStream2::new(); - for variant in &input.variants { + for (variant_idx, variant) in input.variants.iter().enumerate() { + let discriminant_info = DiscriminantInfo { + variant_idx, + discriminants: &discriminants, + use_discriminant, + }; let variant_output = process_variant( variant, + discriminant_info, &cratename, &enum_name, &generics, @@ -47,12 +60,14 @@ pub fn process(input: &ItemEnum, cratename: Path) -> syn::Result { inner_defs.extend(variant_output.inner_struct); add_recursive_defs.extend(variant_output.add_definitions_recursively_call); variants_defs.push(variant_output.variant_entry); + discriminant_variables.push(variant_output.discriminant_variable_assignment); } let type_definitions = quote! { fn add_definitions_recursively(definitions: &mut #cratename::__private::maybestd::collections::BTreeMap<#cratename::schema::Declaration, #cratename::schema::Definition>) { #inner_defs #add_recursive_defs + #(#discriminant_variables)* let definition = #cratename::schema::Definition::Enum { tag_width: 1, variants: #cratename::__private::maybestd::vec![#(#variants_defs),*], @@ -78,12 +93,38 @@ struct VariantOutput { inner_struct: TokenStream2, /// call to `add_definitions_recursively`. add_definitions_recursively_call: TokenStream2, + /// declaration of `u8` variable, holding the value for discriminant of a variant + discriminant_variable_assignment: TokenStream2, /// entry with a variant's declaration, element in vector of whole enum's definition variant_entry: TokenStream2, } +struct DiscriminantInfo<'a> { + variant_idx: usize, + discriminants: &'a Discriminants, + use_discriminant: bool, +} + +fn process_discriminant( + variant_ident: &Ident, + info: DiscriminantInfo<'_>, +) -> syn::Result<(Ident, TokenStream2)> { + let discriminant_value = + info.discriminants + .get(variant_ident, info.use_discriminant, info.variant_idx)?; + + let discriminant_variable_name = format!("discriminant_{}", info.variant_idx); + let discriminant_variable = Ident::new(&discriminant_variable_name, Span::call_site()); + + let discriminant_variable_assignment = quote! { + let #discriminant_variable: u8 = #discriminant_value; + }; + Ok((discriminant_variable, discriminant_variable_assignment)) +} + fn process_variant( variant: &Variant, + discriminant_info: DiscriminantInfo, cratename: &Path, enum_name: &str, enum_generics: &Generics, @@ -101,13 +142,18 @@ fn process_variant( let add_definitions_recursively_call = quote! { <#full_variant_ident #inner_struct_ty_generics as #cratename::BorshSchema>::add_definitions_recursively(definitions); }; + + let (discriminant_variable, discriminant_variable_assignment) = + process_discriminant(&variant.ident, discriminant_info)?; + let variant_entry = quote! { - (#variant_name.to_string(), <#full_variant_ident #inner_struct_ty_generics>::declaration()) + (#discriminant_variable as i64, #variant_name.to_string(), <#full_variant_ident #inner_struct_ty_generics>::declaration()) }; Ok(VariantOutput { inner_struct, add_definitions_recursively_call, variant_entry, + discriminant_variable_assignment, }) } @@ -187,6 +233,43 @@ mod tests { local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); } + #[test] + fn borsh_discriminant_false() { + let item_enum: ItemEnum = syn::parse2(quote! { + #[borsh(use_discriminant = false)] + enum X { + A, + B = 20, + C, + D, + E = 10, + F, + } + }) + .unwrap(); + let actual = process(&item_enum, default_cratename()).unwrap(); + + local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + } + #[test] + fn borsh_discriminant_true() { + let item_enum: ItemEnum = syn::parse2(quote! { + #[borsh(use_discriminant = true)] + enum X { + A, + B = 20, + C, + D, + E = 10, + F, + } + }) + .unwrap(); + let actual = process(&item_enum, default_cratename()).unwrap(); + + local_insta_assert_snapshot!(pretty_print_syn_str(&actual).unwrap()); + } + #[test] fn single_field_enum() { let item_enum: ItemEnum = syn::parse2(quote! { diff --git a/borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_false.snap b/borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_false.snap new file mode 100644 index 000000000..78c60a4b7 --- /dev/null +++ b/borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_false.snap @@ -0,0 +1,65 @@ +--- +source: borsh-derive/src/internals/schema/enums/mod.rs +expression: pretty_print_syn_str(&actual).unwrap() +--- +impl borsh::BorshSchema for X { + fn declaration() -> borsh::schema::Declaration { + "X".to_string() + } + fn add_definitions_recursively( + definitions: &mut borsh::__private::maybestd::collections::BTreeMap< + borsh::schema::Declaration, + borsh::schema::Definition, + >, + ) { + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XA; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XB; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XC; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XD; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XE; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XF; + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; + let discriminant_2: u8 = 2u8; + let discriminant_3: u8 = 3u8; + let discriminant_4: u8 = 4u8; + let discriminant_5: u8 = 5u8; + let definition = borsh::schema::Definition::Enum { + tag_width: 1, + variants: borsh::__private::maybestd::vec![ + (discriminant_0 as i64, "A".to_string(), < XA > ::declaration()), + (discriminant_1 as i64, "B".to_string(), < XB > ::declaration()), + (discriminant_2 as i64, "C".to_string(), < XC > ::declaration()), + (discriminant_3 as i64, "D".to_string(), < XD > ::declaration()), + (discriminant_4 as i64, "E".to_string(), < XE > ::declaration()), + (discriminant_5 as i64, "F".to_string(), < XF > ::declaration()) + ], + }; + borsh::schema::add_definition(Self::declaration(), definition, definitions); + } +} + diff --git a/borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_true.snap b/borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_true.snap new file mode 100644 index 000000000..0cfe44c56 --- /dev/null +++ b/borsh-derive/src/internals/schema/enums/snapshots/borsh_discriminant_true.snap @@ -0,0 +1,65 @@ +--- +source: borsh-derive/src/internals/schema/enums/mod.rs +expression: pretty_print_syn_str(&actual).unwrap() +--- +impl borsh::BorshSchema for X { + fn declaration() -> borsh::schema::Declaration { + "X".to_string() + } + fn add_definitions_recursively( + definitions: &mut borsh::__private::maybestd::collections::BTreeMap< + borsh::schema::Declaration, + borsh::schema::Definition, + >, + ) { + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XA; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XB; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XC; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XD; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XE; + #[allow(dead_code)] + #[derive(borsh::BorshSchema)] + #[borsh(crate = "borsh")] + struct XF; + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + ::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0; + let discriminant_1: u8 = 20; + let discriminant_2: u8 = 20 + 1; + let discriminant_3: u8 = 20 + 1 + 1; + let discriminant_4: u8 = 10; + let discriminant_5: u8 = 10 + 1; + let definition = borsh::schema::Definition::Enum { + tag_width: 1, + variants: borsh::__private::maybestd::vec![ + (discriminant_0 as i64, "A".to_string(), < XA > ::declaration()), + (discriminant_1 as i64, "B".to_string(), < XB > ::declaration()), + (discriminant_2 as i64, "C".to_string(), < XC > ::declaration()), + (discriminant_3 as i64, "D".to_string(), < XD > ::declaration()), + (discriminant_4 as i64, "E".to_string(), < XE > ::declaration()), + (discriminant_5 as i64, "F".to_string(), < XF > ::declaration()) + ], + }; + borsh::schema::add_definition(Self::declaration(), definition, definitions); + } +} + diff --git a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum.snap b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum.snap index 027619667..82b5e1262 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum.snap @@ -35,12 +35,18 @@ impl borsh::BorshSchema for A { ::add_definitions_recursively(definitions); ::add_definitions_recursively(definitions); ::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; + let discriminant_2: u8 = 2u8; + let discriminant_3: u8 = 3u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("Bacon".to_string(), < ABacon > ::declaration()), ("Eggs".to_string(), < - AEggs > ::declaration()), ("Salad".to_string(), < ASalad > - ::declaration()), ("Sausage".to_string(), < ASausage > ::declaration()) + (discriminant_0 as i64, "Bacon".to_string(), < ABacon > ::declaration()), + (discriminant_1 as i64, "Eggs".to_string(), < AEggs > ::declaration()), + (discriminant_2 as i64, "Salad".to_string(), < ASalad > ::declaration()), + (discriminant_3 as i64, "Sausage".to_string(), < ASausage > + ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics.snap b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics.snap index bc4c91503..01f7ae6c5 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics.snap @@ -42,13 +42,18 @@ where ::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; + let discriminant_2: u8 = 2u8; + let discriminant_3: u8 = 3u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("Bacon".to_string(), < ABacon > ::declaration()), ("Eggs".to_string(), < - AEggs > ::declaration()), ("Salad".to_string(), < ASalad < C > > - ::declaration()), ("Sausage".to_string(), < ASausage < W > > - ::declaration()) + (discriminant_0 as i64, "Bacon".to_string(), < ABacon > ::declaration()), + (discriminant_1 as i64, "Eggs".to_string(), < AEggs > ::declaration()), + (discriminant_2 as i64, "Salad".to_string(), < ASalad < C > > + ::declaration()), (discriminant_3 as i64, "Sausage".to_string(), < + ASausage < W > > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_named_field.snap b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_named_field.snap index 99f616396..25e9e0431 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_named_field.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_named_field.snap @@ -44,13 +44,18 @@ where ::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; + let discriminant_2: u8 = 2u8; + let discriminant_3: u8 = 3u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("Bacon".to_string(), < ABacon > ::declaration()), ("Eggs".to_string(), < - AEggs > ::declaration()), ("Salad".to_string(), < ASalad < C > > - ::declaration()), ("Sausage".to_string(), < ASausage < W, U > > - ::declaration()) + (discriminant_0 as i64, "Bacon".to_string(), < ABacon > ::declaration()), + (discriminant_1 as i64, "Eggs".to_string(), < AEggs > ::declaration()), + (discriminant_2 as i64, "Salad".to_string(), < ASalad < C > > + ::declaration()), (discriminant_3 as i64, "Sausage".to_string(), < + ASausage < W, U > > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_tuple_field.snap b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_tuple_field.snap index b9ee7f0c5..5bf85ecfe 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_tuple_field.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/complex_enum_generics_borsh_skip_tuple_field.snap @@ -43,13 +43,18 @@ where ::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; + let discriminant_2: u8 = 2u8; + let discriminant_3: u8 = 3u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("Bacon".to_string(), < ABacon > ::declaration()), ("Eggs".to_string(), < - AEggs > ::declaration()), ("Salad".to_string(), < ASalad < C > > - ::declaration()), ("Sausage".to_string(), < ASausage < W > > - ::declaration()) + (discriminant_0 as i64, "Bacon".to_string(), < ABacon > ::declaration()), + (discriminant_1 as i64, "Eggs".to_string(), < AEggs > ::declaration()), + (discriminant_2 as i64, "Salad".to_string(), < ASalad < C > > + ::declaration()), (discriminant_3 as i64, "Sausage".to_string(), < + ASausage < W > > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/filter_foreign_attrs.snap b/borsh-derive/src/internals/schema/enums/snapshots/filter_foreign_attrs.snap index 273b550ee..c1ff9ec3c 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/filter_foreign_attrs.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/filter_foreign_attrs.snap @@ -29,11 +29,14 @@ impl borsh::BorshSchema for A { } ::add_definitions_recursively(definitions); ::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("B".to_string(), < AB > ::declaration()), ("Negative".to_string(), < - ANegative > ::declaration()) + (discriminant_0 as i64, "B".to_string(), < AB > ::declaration()), + (discriminant_1 as i64, "Negative".to_string(), < ANegative > + ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type.snap b/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type.snap index 0db595cc6..404dce45d 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type.snap @@ -55,11 +55,14 @@ where as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("B".to_string(), < EnumParametrizedB < K, V > > ::declaration()), ("C" - .to_string(), < EnumParametrizedC < T > > ::declaration()) + (discriminant_0 as i64, "B".to_string(), < EnumParametrizedB < K, V > > + ::declaration()), (discriminant_1 as i64, "C".to_string(), < + EnumParametrizedC < T > > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type_param_override.snap b/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type_param_override.snap index 1b56f94f5..7effbbdf8 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type_param_override.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/generic_associated_type_param_override.snap @@ -56,11 +56,14 @@ where as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("B".to_string(), < EnumParametrizedB < K, V > > ::declaration()), ("C" - .to_string(), < EnumParametrizedC < T > > ::declaration()) + (discriminant_0 as i64, "B".to_string(), < EnumParametrizedB < K, V > > + ::declaration()), (discriminant_1 as i64, "C".to_string(), < + EnumParametrizedC < T > > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/recursive_enum.snap b/borsh-derive/src/internals/schema/enums/snapshots/recursive_enum.snap index a1b906dfb..b085c8a65 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/recursive_enum.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/recursive_enum.snap @@ -36,11 +36,14 @@ where struct AC(K, Vec); as borsh::BorshSchema>::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("B".to_string(), < AB < K, V > > ::declaration()), ("C".to_string(), < - AC < K > > ::declaration()) + (discriminant_0 as i64, "B".to_string(), < AB < K, V > > + ::declaration()), (discriminant_1 as i64, "C".to_string(), < AC < K > > + ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/simple_enum.snap b/borsh-derive/src/internals/schema/enums/snapshots/simple_enum.snap index 603c0f776..980854715 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/simple_enum.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/simple_enum.snap @@ -22,11 +22,13 @@ impl borsh::BorshSchema for A { struct AEggs; ::add_definitions_recursively(definitions); ::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("Bacon".to_string(), < ABacon > ::declaration()), ("Eggs".to_string(), < - AEggs > ::declaration()) + (discriminant_0 as i64, "Bacon".to_string(), < ABacon > ::declaration()), + (discriminant_1 as i64, "Eggs".to_string(), < AEggs > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/simple_enum_with_custom_crate.snap b/borsh-derive/src/internals/schema/enums/snapshots/simple_enum_with_custom_crate.snap index 538e501a1..8b8240e05 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/simple_enum_with_custom_crate.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/simple_enum_with_custom_crate.snap @@ -26,11 +26,13 @@ impl reexporter::borsh::BorshSchema for A { ::add_definitions_recursively( definitions, ); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = reexporter::borsh::schema::Definition::Enum { tag_width: 1, variants: reexporter::borsh::__private::maybestd::vec![ - ("Bacon".to_string(), < ABacon > ::declaration()), ("Eggs".to_string(), < - AEggs > ::declaration()) + (discriminant_0 as i64, "Bacon".to_string(), < ABacon > ::declaration()), + (discriminant_1 as i64, "Eggs".to_string(), < AEggs > ::declaration()) ], }; reexporter::borsh::schema::add_definition( diff --git a/borsh-derive/src/internals/schema/enums/snapshots/single_field_enum.snap b/borsh-derive/src/internals/schema/enums/snapshots/single_field_enum.snap index c3bf310dd..d91d89e14 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/single_field_enum.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/single_field_enum.snap @@ -17,10 +17,11 @@ impl borsh::BorshSchema for A { #[borsh(crate = "borsh")] struct ABacon; ::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("Bacon".to_string(), < ABacon > ::declaration()) + (discriminant_0 as i64, "Bacon".to_string(), < ABacon > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/trailing_comma_generics.snap b/borsh-derive/src/internals/schema/enums/snapshots/trailing_comma_generics.snap index 151473bd3..3d918330b 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/trailing_comma_generics.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/trailing_comma_generics.snap @@ -39,11 +39,14 @@ where B: Display + Debug; as borsh::BorshSchema>::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("Left".to_string(), < SideLeft < A > > ::declaration()), ("Right" - .to_string(), < SideRight < B > > ::declaration()) + (discriminant_0 as i64, "Left".to_string(), < SideLeft < A > > + ::declaration()), (discriminant_1 as i64, "Right".to_string(), < + SideRight < B > > ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/internals/schema/enums/snapshots/with_funcs_attr.snap b/borsh-derive/src/internals/schema/enums/snapshots/with_funcs_attr.snap index 766464e7f..152d7b54e 100644 --- a/borsh-derive/src/internals/schema/enums/snapshots/with_funcs_attr.snap +++ b/borsh-derive/src/internals/schema/enums/snapshots/with_funcs_attr.snap @@ -40,11 +40,14 @@ where ); ::add_definitions_recursively(definitions); as borsh::BorshSchema>::add_definitions_recursively(definitions); + let discriminant_0: u8 = 0u8; + let discriminant_1: u8 = 1u8; let definition = borsh::schema::Definition::Enum { tag_width: 1, variants: borsh::__private::maybestd::vec![ - ("C3".to_string(), < CC3 > ::declaration()), ("C4".to_string(), < CC4 < - K, V > > ::declaration()) + (discriminant_0 as i64, "C3".to_string(), < CC3 > ::declaration()), + (discriminant_1 as i64, "C4".to_string(), < CC4 < K, V > > + ::declaration()) ], }; borsh::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh-derive/src/lib.rs b/borsh-derive/src/lib.rs index eba6912f9..dc32becfb 100644 --- a/borsh-derive/src/lib.rs +++ b/borsh-derive/src/lib.rs @@ -134,7 +134,7 @@ enum A { To have explicit discriminant value serialized as is, you must specify `borsh(use_discriminant=true)` for enum. ```ignore -#[derive(BorsSerialize)] +#[derive(BorshSerialize)] #[borsh(use_discriminant = true)] enum B { A @@ -739,7 +739,67 @@ struct B { } ``` -### 2. `#[borsh(skip)]` (field level attribute) +### 2. `borsh(use_discriminant=)` (item level attribute) +This attribute is only applicable to enums. +`use_discriminant` allows to override the default behavior of serialization of enums with explicit discriminant. +`use_discriminant` is `false` behaves like version of borsh of 0.10.3. +You must specify `use_discriminant` for all enums with explicit discriminants in your project. + +This is equivalent of borsh version 0.10.3 (explicit discriminant is ignored and this enum is equivalent to `A` without explicit discriminant): +```ignore +#[derive(BorshSchema)] +#[borsh(use_discriminant = false)] +enum A { + A + B = 10, +} +``` + +To have explicit discriminant value serialized as is, you must specify `borsh(use_discriminant=true)` for enum. +```ignore +#[derive(BorshSchema)] +#[borsh(use_discriminant = true)] +enum B { + A + B = 10, +} +``` + +###### borsh, expressions, evaluating to `isize`, as discriminant +This case is not supported: +```ignore +const fn discrim() -> isize { + 0x14 +} + +#[derive(BorshSchema)] +#[borsh(use_discriminant = true)] +enum X { + A, + B = discrim(), // expressions, evaluating to `isize`, which are allowed outside of `borsh` context + C, + D, + E = 10, + F, +} +``` + +###### borsh explicit discriminant does not support literal values outside of u8 range +This is not supported: +```ignore +#[derive(BorshSchema)] +#[borsh(use_discriminant = true)] +enum X { + A, + B = 0x100, // literal values outside of `u8` range + C, + D, + E = 10, + F, +} +``` + +### 3. `#[borsh(skip)]` (field level attribute) `#[borsh(skip)]` makes derive skip including schema from annotated field into schema's implementation. @@ -754,7 +814,7 @@ struct A { } ``` -### 3. `#[borsh(schema(params = ...))]` (field level attribute) +### 4. `#[borsh(schema(params = ...))]` (field level attribute) ###### syntax @@ -825,7 +885,7 @@ where `#[borsh(schema(params = ...))]` is not allowed to be used simultaneously with `#[borsh(skip)]`. -### 4. `#[borsh(schema(with_funcs(declaration = ..., definitions = ...)))]` (field level attribute) +### 5. `#[borsh(schema(with_funcs(declaration = ..., definitions = ...)))]` (field level attribute) ###### syntax diff --git a/borsh/src/schema.rs b/borsh/src/schema.rs index 3fbcdae45..a1b5dc84a 100644 --- a/borsh/src/schema.rs +++ b/borsh/src/schema.rs @@ -35,6 +35,8 @@ pub use container_ext::{SchemaContainerValidateError, SchemaMaxSerializedSizeErr pub type Declaration = String; /// The type that we use for the name of the variant. pub type VariantName = String; +/// The type that we use for value of discriminant. +pub type DiscriminantValue = i64; /// The name of the field in the struct (can be used to convert JSON to Borsh using the schema). pub type FieldName = String; /// The type that we use to represent the definition of the Borsh type. @@ -119,7 +121,7 @@ pub enum Definition { tag_width: u8, /// Possible variants of the enumeration. - variants: Vec<(VariantName, Declaration)>, + variants: Vec<(DiscriminantValue, VariantName, Declaration)>, }, /// A structure, structurally similar to a tuple. @@ -453,8 +455,8 @@ where let definition = Definition::Enum { tag_width: 1, variants: vec![ - ("None".to_string(), <()>::declaration()), - ("Some".to_string(), T::declaration()), + (0u8 as i64, "None".to_string(), <()>::declaration()), + (1u8 as i64, "Some".to_string(), T::declaration()), ], }; add_definition(Self::declaration(), definition, definitions); @@ -476,8 +478,8 @@ where let definition = Definition::Enum { tag_width: 1, variants: vec![ - ("Ok".to_string(), T::declaration()), - ("Err".to_string(), E::declaration()), + (1u8 as i64, "Ok".to_string(), T::declaration()), + (0u8 as i64, "Err".to_string(), E::declaration()), ], }; add_definition(Self::declaration(), definition, definitions); @@ -713,8 +715,8 @@ mod tests { "Option" => Definition::Enum { tag_width: 1, variants: vec![ - ("None".to_string(), "nil".to_string()), - ("Some".to_string(), "u64".to_string()), + (0, "None".to_string(), "nil".to_string()), + (1, "Some".to_string(), "u64".to_string()), ] }, "u64" => Definition::Primitive(8), @@ -735,15 +737,15 @@ mod tests { "Option" => Definition::Enum { tag_width: 1, variants: vec![ - ("None".to_string(), "nil".to_string()), - ("Some".to_string(), "u64".to_string()), + (0, "None".to_string(), "nil".to_string()), + (1, "Some".to_string(), "u64".to_string()), ] }, "Option>" => Definition::Enum { tag_width: 1, variants: vec![ - ("None".to_string(), "nil".to_string()), - ("Some".to_string(), "Option".to_string()), + (0, "None".to_string(), "nil".to_string()), + (1, "Some".to_string(), "Option".to_string()), ] }, "u64" => Definition::Primitive(8), diff --git a/borsh/src/schema/container_ext/max_size.rs b/borsh/src/schema/container_ext/max_size.rs index d3ddb1821..b71436bd4 100644 --- a/borsh/src/schema/container_ext/max_size.rs +++ b/borsh/src/schema/container_ext/max_size.rs @@ -136,7 +136,7 @@ fn max_serialized_size_impl<'a>( variants, }) => { let mut max = 0; - for (_, variant) in variants { + for (_, _, variant) in variants { let sz = max_serialized_size_impl(ONE, variant, schema, stack)?; max = max.max(sz); } @@ -242,7 +242,7 @@ fn is_zero_size_impl<'a>( variants, }) => all( variants.iter(), - |(_variant_name, declaration)| declaration, + |(_variant_discrim, _variant_name, declaration)| declaration, schema, stack, )?, @@ -449,8 +449,8 @@ mod tests { let definition = Definition::Enum { tag_width: N, variants: vec![ - ("Just".into(), T::declaration()), - ("Nothing".into(), "nil".into()), + (0, "Just".into(), T::declaration()), + (1, "Nothing".into(), "nil".into()), ], }; crate::schema::add_definition(Self::declaration(), definition, definitions); diff --git a/borsh/src/schema/container_ext/validate.rs b/borsh/src/schema/container_ext/validate.rs index e5a945d2e..e8957dc31 100644 --- a/borsh/src/schema/container_ext/validate.rs +++ b/borsh/src/schema/container_ext/validate.rs @@ -110,7 +110,7 @@ fn validate_impl<'a>( if *tag_width > U64_LEN { return Err(Error::TagTooWide(declaration.to_string())); } - for (_, variant) in variants { + for (_, _, variant) in variants { validate_impl(variant, schema, stack)?; } } diff --git a/borsh/tests/snapshots/test_schema_enums__complex_enum_with_schema.snap b/borsh/tests/snapshots/test_schema_enums__complex_enum_with_schema.snap index a9c7f34d7..e852f2751 100644 --- a/borsh/tests/snapshots/test_schema_enums__complex_enum_with_schema.snap +++ b/borsh/tests/snapshots/test_schema_enums__complex_enum_with_schema.snap @@ -23,6 +23,14 @@ expression: data 0, 0, 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 5, 0, 0, @@ -42,6 +50,14 @@ expression: data 99, 111, 110, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 4, 0, 0, @@ -59,6 +75,14 @@ expression: data 103, 103, 115, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 5, 0, 0, @@ -78,6 +102,14 @@ expression: data 108, 97, 100, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, 7, 0, 0, diff --git a/borsh/tests/test_enum_discriminants.rs b/borsh/tests/test_enum_discriminants.rs index d8de987b6..2fd9473cb 100644 --- a/borsh/tests/test_enum_discriminants.rs +++ b/borsh/tests/test_enum_discriminants.rs @@ -8,6 +8,7 @@ extern crate alloc; 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)] @@ -183,3 +184,131 @@ fn test_discriminant_serde() { assert_eq!(from_slice::(&data).unwrap(), values[index]); } } + +#[cfg(feature = "unstable__schema")] +mod schema { + #[cfg(not(feature = "std"))] + use alloc::{collections::BTreeMap, string::ToString, vec}; + + #[cfg(feature = "std")] + use std::collections::BTreeMap; + + macro_rules! map( + () => { BTreeMap::new() }; + { $($key:expr => $value:expr),+ } => { + { + let mut m = BTreeMap::new(); + $( + m.insert($key.to_string(), $value); + )+ + m + } + }; + ); + + use borsh::{ + schema::{Definition, Fields}, + BorshSchema, + }; + + #[allow(unused)] + #[derive(BorshSchema)] + #[borsh(use_discriminant = true)] + #[repr(i16)] + enum XY { + A, + B = 20, + C, + D(u32, u32), + E = 10, + F(u64), + } + + #[test] + fn test_schema_discriminant_no_unit_type() { + assert_eq!("XY".to_string(), XY::declaration()); + let mut defs = Default::default(); + XY::add_definitions_recursively(&mut defs); + assert_eq!( + map! { + "XY" => Definition::Enum { + tag_width: 1, + variants: vec![ + (0, "A".to_string(), "XYA".to_string()), + (20, "B".to_string(), "XYB".to_string()), + (21, "C".to_string(), "XYC".to_string()), + (22, "D".to_string(), "XYD".to_string()), + (10, "E".to_string(), "XYE".to_string()), + (11, "F".to_string(), "XYF".to_string()) + ] + }, + "XYA" => Definition::Struct{ fields: Fields::Empty }, + "XYB" => Definition::Struct{ fields: Fields::Empty }, + "XYC" => Definition::Struct{ fields: Fields::Empty }, + "XYD" => Definition::Struct{ fields: Fields::UnnamedFields( + vec!["u32".to_string(), "u32".to_string()] + )}, + "XYE" => Definition::Struct{ fields: Fields::Empty }, + "XYF" => Definition::Struct{ fields: Fields::UnnamedFields( + vec!["u64".to_string()] + + )}, + "u32" => Definition::Primitive(4), + "u64" => Definition::Primitive(8) + }, + defs + ); + } + + #[allow(unused)] + #[derive(BorshSchema)] + #[borsh(use_discriminant = false)] + #[repr(i16)] + enum XYNoDiscriminant { + A, + B = 20, + C, + D(u32, u32), + E = 10, + F(u64), + } + + #[test] + fn test_schema_discriminant_no_unit_type_no_use_discriminant() { + assert_eq!( + "XYNoDiscriminant".to_string(), + XYNoDiscriminant::declaration() + ); + let mut defs = Default::default(); + XYNoDiscriminant::add_definitions_recursively(&mut defs); + assert_eq!( + map! { + "XYNoDiscriminant" => Definition::Enum { + tag_width: 1, + variants: vec![ + (0, "A".to_string(), "XYNoDiscriminantA".to_string()), + (1, "B".to_string(), "XYNoDiscriminantB".to_string()), + (2, "C".to_string(), "XYNoDiscriminantC".to_string()), + (3, "D".to_string(), "XYNoDiscriminantD".to_string()), + (4, "E".to_string(), "XYNoDiscriminantE".to_string()), + (5, "F".to_string(), "XYNoDiscriminantF".to_string()) + ] + }, + "XYNoDiscriminantA" => Definition::Struct{ fields: Fields::Empty }, + "XYNoDiscriminantB" => Definition::Struct{ fields: Fields::Empty }, + "XYNoDiscriminantC" => Definition::Struct{ fields: Fields::Empty }, + "XYNoDiscriminantD" => Definition::Struct{ fields: Fields::UnnamedFields( + vec!["u32".to_string(), "u32".to_string()] + )}, + "XYNoDiscriminantE" => Definition::Struct{ fields: Fields::Empty }, + "XYNoDiscriminantF" => Definition::Struct{ fields: Fields::UnnamedFields( + vec!["u64".to_string()] + + )}, + "u32" => Definition::Primitive(4), + "u64" => Definition::Primitive(8) + }, + defs + ); + } +} diff --git a/borsh/tests/test_schema_enums.rs b/borsh/tests/test_schema_enums.rs index 5c796d5be..cdb532cf9 100644 --- a/borsh/tests/test_schema_enums.rs +++ b/borsh/tests/test_schema_enums.rs @@ -48,7 +48,7 @@ pub fn simple_enum() { "AEggs" => Definition::Struct{ fields: Fields::Empty }, "A" => Definition::Enum { tag_width: 1, - variants: vec![("Bacon".to_string(), "ABacon".to_string()), ("Eggs".to_string(), "AEggs".to_string())] + variants: vec![(0, "Bacon".to_string(), "ABacon".to_string()), (1, "Eggs".to_string(), "AEggs".to_string())] } }, defs @@ -69,7 +69,7 @@ pub fn single_field_enum() { "ABacon" => Definition::Struct {fields: Fields::Empty}, "A" => Definition::Enum { tag_width: 1, - variants: vec![("Bacon".to_string(), "ABacon".to_string())] + variants: vec![(0, "Bacon".to_string(), "ABacon".to_string())] } }, defs @@ -185,10 +185,10 @@ pub fn complex_enum_with_schema() { "A" => Definition::Enum { tag_width: 1, variants: vec![ - ("Bacon".to_string(), "ABacon".to_string()), - ("Eggs".to_string(), "AEggs".to_string()), - ("Salad".to_string(), "ASalad".to_string()), - ("Sausage".to_string(), "ASausage".to_string()) + (0, "Bacon".to_string(), "ABacon".to_string()), + (1, "Eggs".to_string(), "AEggs".to_string()), + (2, "Salad".to_string(), "ASalad".to_string()), + (3, "Sausage".to_string(), "ASausage".to_string()) ] }, "Wrapper" => Definition::Struct {fields: Fields::Empty}, @@ -247,10 +247,10 @@ pub fn complex_enum_generics() { "A" => Definition::Enum { tag_width: 1, variants: vec![ - ("Bacon".to_string(), "ABacon".to_string()), - ("Eggs".to_string(), "AEggs".to_string()), - ("Salad".to_string(), "ASalad".to_string()), - ("Sausage".to_string(), "ASausage".to_string()) + (0, "Bacon".to_string(), "ABacon".to_string()), + (1, "Eggs".to_string(), "AEggs".to_string()), + (2, "Salad".to_string(), "ASalad".to_string()), + (3, "Sausage".to_string(), "ASausage".to_string()) ] }, "Wrapper" => Definition::Struct {fields: Fields::Empty}, @@ -273,8 +273,8 @@ fn common_map() -> BTreeMap { "EnumParametrized" => Definition::Enum { tag_width: 1, variants: vec![ - ("B".to_string(), "EnumParametrizedB".to_string()), - ("C".to_string(), "EnumParametrizedC".to_string()) + (0, "B".to_string(), "EnumParametrizedB".to_string()), + (1, "C".to_string(), "EnumParametrizedC".to_string()) ] }, "EnumParametrizedB" => Definition::Struct { fields: Fields::NamedFields(vec![ diff --git a/borsh/tests/test_schema_nested.rs b/borsh/tests/test_schema_nested.rs index ca002cf27..7d3c5e563 100644 --- a/borsh/tests/test_schema_nested.rs +++ b/borsh/tests/test_schema_nested.rs @@ -71,19 +71,19 @@ pub fn duplicated_instantiations() { "A>" => Definition::Enum { tag_width: 1, variants: vec![ - ("Bacon".to_string(), "ABacon".to_string()), - ("Eggs".to_string(), "AEggs".to_string()), - ("Salad".to_string(), "ASalad".to_string()), - ("Sausage".to_string(), "ASausage>".to_string()) + (0, "Bacon".to_string(), "ABacon".to_string()), + (1, "Eggs".to_string(), "AEggs".to_string()), + (2, "Salad".to_string(), "ASalad".to_string()), + (3, "Sausage".to_string(), "ASausage>".to_string()) ] }, "A" => Definition::Enum { tag_width: 1, variants: vec![ - ("Bacon".to_string(), "ABacon".to_string()), - ("Eggs".to_string(), "AEggs".to_string()), - ("Salad".to_string(), "ASalad".to_string()), - ("Sausage".to_string(), "ASausage".to_string()) + (0, "Bacon".to_string(), "ABacon".to_string()), + (1, "Eggs".to_string(), "AEggs".to_string()), + (2, "Salad".to_string(), "ASalad".to_string()), + (3, "Sausage".to_string(), "ASausage".to_string()) ] }, "ABacon" => Definition::Struct {fields: Fields::Empty}, @@ -103,15 +103,15 @@ pub fn duplicated_instantiations() { "Option" => Definition::Enum { tag_width: 1, variants: vec![ - ("None".to_string(), "nil".to_string()), - ("Some".to_string(), "string".to_string()) + (0, "None".to_string(), "nil".to_string()), + (1, "Some".to_string(), "string".to_string()) ] }, "Option" => Definition::Enum { tag_width: 1, variants: vec![ - ("None".to_string(), "nil".to_string()), - ("Some".to_string(), "u64".to_string()) + (0, "None".to_string(), "nil".to_string()), + (1, "Some".to_string(), "u64".to_string()) ] }, "Tomatoes" => Definition::Struct {fields: Fields::Empty}, diff --git a/borsh/tests/test_schema_recursive.rs b/borsh/tests/test_schema_recursive.rs index 97a6e7968..7b44dd38d 100644 --- a/borsh/tests/test_schema_recursive.rs +++ b/borsh/tests/test_schema_recursive.rs @@ -85,8 +85,8 @@ pub fn recursive_enum_schema() { "ERecD" => Definition::Enum { tag_width: 1, variants: vec![ - ("B".to_string(), "ERecDB".to_string()), - ("C".to_string(), "ERecDC".to_string()), + (0, "B".to_string(), "ERecDB".to_string()), + (1, "C".to_string(), "ERecDC".to_string()), ] }, "ERecDB" => Definition::Struct { diff --git a/borsh/tests/test_schema_with.rs b/borsh/tests/test_schema_with.rs index ca7c38f0a..61704931e 100644 --- a/borsh/tests/test_schema_with.rs +++ b/borsh/tests/test_schema_with.rs @@ -144,8 +144,8 @@ pub fn enum_overriden() { "C" => Definition::Enum { tag_width: 1, variants: vec![ - ("C3".to_string(), "CC3".to_string()), - ("C4".to_string(), "CC4".to_string()) + (0, "C3".to_string(), "CC3".to_string()), + (1, "C4".to_string(), "CC4".to_string()) ] }, "CC3" => Definition::Struct { fields: Fields::UnnamedFields(vec!["u64".to_string(), "u64".to_string()]) },