Skip to content

Commit f341871

Browse files
authored
Tweak enum serialization to generate better LLVM IR and more compact code (#77)
Change enum serialization form match self { Enum::Variant1(field1, field2, ...) => { // serialize variant idx let variant_idx: u8 = 0; writer.write_all(&variant_idx.to_le_bytes())?; // serialize variant fields BorshSerialize::serialize(field1, writer)?; BorshSerialize::serialize(field2, writer)?; ... } Enum::Variant2(field1, field2, ...) => { let variant_idx: u8 = 1; writer.write_all(&variant_idx.to_le_bytes())?; // serialize variant fields BorshSerialize::serialize(field1, writer)?; BorshSerialize::serialize(field2, writer)?; ... } ... } To: let variant_idx: u8 = match self { Enum::Variant1(..) => 0, Enum::Variant2(..) => 1, ... }; // serialize variant_idx writer.write_all(&variant_idx.to_le_bytes())?; match self { Enum::Variant1(field1, field2, ...) => { // serialize variant fields BorshSerialize::serialize(field1, writer)?; BorshSerialize::serialize(field2, writer)?; ... } Enum::Variant2(field1, field2, ...) => { // serialize variant fields BorshSerialize::serialize(field1, writer)?; BorshSerialize::serialize(field2, writer)?; ... } ... } The latter generates better LLVM IR, and avoids writer.write_all(&variant_idx.to_le_bytes())?; from being inlined into each match branch.
1 parent 36e63e7 commit f341871

1 file changed

Lines changed: 20 additions & 6 deletions

File tree

borsh-derive-internal/src/enum_ser.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ pub fn enum_ser(input: &ItemEnum, cratename: Ident) -> syn::Result<TokenStream2>
1616
},
1717
Clone::clone,
1818
);
19-
let mut body = TokenStream2::new();
19+
let mut variant_idx_body = TokenStream2::new();
20+
let mut fields_body = TokenStream2::new();
2021
for (variant_idx, variant) in input.variants.iter().enumerate() {
2122
let variant_idx = u8::try_from(variant_idx).expect("up to 256 enum variants are supported");
2223
let variant_ident = &variant.ident;
@@ -44,6 +45,9 @@ pub fn enum_ser(input: &ItemEnum, cratename: Ident) -> syn::Result<TokenStream2>
4445
})
4546
}
4647
variant_header = quote! { { #variant_header }};
48+
variant_idx_body.extend(quote!(
49+
#name::#variant_ident { .. } => #variant_idx,
50+
));
4751
}
4852
Fields::Unnamed(fields) => {
4953
for (field_idx, field) in fields.unnamed.iter().enumerate() {
@@ -72,22 +76,32 @@ pub fn enum_ser(input: &ItemEnum, cratename: Ident) -> syn::Result<TokenStream2>
7276
}
7377
}
7478
variant_header = quote! { ( #variant_header )};
79+
variant_idx_body.extend(quote!(
80+
#name::#variant_ident(..) => #variant_idx,
81+
));
82+
}
83+
Fields::Unit => {
84+
variant_idx_body.extend(quote!(
85+
#name::#variant_ident => #variant_idx,
86+
));
7587
}
76-
Fields::Unit => {}
7788
}
78-
body.extend(quote!(
89+
fields_body.extend(quote!(
7990
#name::#variant_ident #variant_header => {
80-
let variant_idx: u8 = #variant_idx;
81-
writer.write_all(&variant_idx.to_le_bytes())?;
8291
#variant_body
8392
}
8493
))
8594
}
8695
Ok(quote! {
8796
impl #impl_generics #cratename::ser::BorshSerialize for #name #ty_generics #where_clause {
8897
fn serialize<W: #cratename::maybestd::io::Write>(&self, writer: &mut W) -> core::result::Result<(), #cratename::maybestd::io::Error> {
98+
let variant_idx: u8 = match self {
99+
#variant_idx_body
100+
};
101+
writer.write_all(&variant_idx.to_le_bytes())?;
102+
89103
match self {
90-
#body
104+
#fields_body
91105
}
92106
Ok(())
93107
}

0 commit comments

Comments
 (0)