Skip to content

Commit

Permalink
feat: support enum serializaiton
Browse files Browse the repository at this point in the history
  • Loading branch information
jiacai2050 committed Aug 26, 2024
1 parent 8d5f8f3 commit 57ce6bf
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 9 deletions.
3 changes: 3 additions & 0 deletions rust/fury-core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ pub enum Language {

#[derive(PartialEq)]
pub enum Mode {
// Type declaration must be consistent between serialization peer and deserialization peer.
SchemaConsistent,
// Type declaration can be different between serialization peer and deserialization peer.
// They can add/delete fields independently.
Compatible,
}

Expand Down
51 changes: 51 additions & 0 deletions rust/fury-derive/src/object/derive_enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use proc_macro2::TokenStream;
use quote::quote;
use syn::DataEnum;

pub fn gen_type_def(_data_enum: &DataEnum) -> TokenStream {
quote! {
fn type_def(fury: &fury_core::fury::Fury) -> Vec<u8> {
Vec::new()
}
}
}

pub fn gen_write(data_enum: &DataEnum) -> TokenStream {
let variant_idents: Vec<_> = data_enum.variants.iter().map(|v| &v.ident).collect();
let variant_values: Vec<_> = (0..variant_idents.len()).map(|v| v as i32).collect();

quote! {
fn write(&self, context: &mut fury_core::resolver::context::WriteContext) {
match self {
#(
Self::#variant_idents => {
context.writer.var_int32(#variant_values);
}
)*
}
}

fn reserved_space() -> usize {
4
}
}
}

pub fn gen_read(data_enum: &DataEnum) -> TokenStream {
let variant_idents: Vec<_> = data_enum.variants.iter().map(|v| &v.ident).collect();
let variant_values: Vec<_> = (0..variant_idents.len()).map(|v| v as i32).collect();

quote! {
fn read(
context: &mut fury_core::resolver::context::ReadContext,
) -> Result<Self, fury_core::error::Error> {
let v = context.reader.var_int32();
match v {
#(
#variant_values => Ok(Self::#variant_idents),
)*
_ => panic!("unknown value"),
}
}
}
}
1 change: 1 addition & 0 deletions rust/fury-derive/src/object/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub fn gen_in_struct_impl(fields: &[&Field]) -> TokenStream {
#type_def_token_stream
}
}

pub fn gen() -> TokenStream {
quote! {
fn get_type_id(fury: &fury_core::fury::Fury) -> i16 {
Expand Down
1 change: 1 addition & 0 deletions rust/fury-derive/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// specific language governing permissions and limitations
// under the License.

mod derive_enum;
mod misc;
mod read;
mod serializer;
Expand Down
27 changes: 18 additions & 9 deletions rust/fury-derive/src/object/serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,37 @@
// specific language governing permissions and limitations
// under the License.

use crate::object::{misc, read, write};
use crate::object::{derive_enum, misc, read, write};
use crate::util::sorted_fields;
use proc_macro::TokenStream;
use quote::quote;

pub fn derive_serializer(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let fields = match &ast.data {
syn::Data::Struct(s) => sorted_fields(&s.fields),
_ => {
panic!("only struct be supported")
let (type_def_token_stream, write_token_stream, read_token_stream) = match &ast.data {
syn::Data::Struct(s) => {
let fields = sorted_fields(&s.fields);
(
misc::gen_in_struct_impl(&fields),
write::gen(&fields),
read::gen(&fields),
)
}
syn::Data::Enum(s) => (
derive_enum::gen_type_def(&s),
derive_enum::gen_write(&s),
derive_enum::gen_read(&s),
),
syn::Data::Union(_) => {
panic!("Union is not supported")
}
};

let misc_token_stream = misc::gen();
let struct_impl_token_stream = misc::gen_in_struct_impl(&fields);
let write_token_stream = write::gen(&fields);
let read_token_stream = read::gen(&fields);

let gen = quote! {
impl fury_core::serializer::StructSerializer for #name {
#struct_impl_token_stream
#type_def_token_stream
}
impl fury_core::types::FuryGeneralList for #name {}
impl fury_core::serializer::Serializer for #name {
Expand Down
16 changes: 16 additions & 0 deletions rust/tests/tests/test_complex_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ fn any() {
assert!(obj.f1.is::<Animal>())
}

#[test]
fn enum_without_payload() {
#[derive(Fury, Debug, PartialEq)]
enum Color {
Green,
Red,
Blue,
}
let mut fury = Fury::default();
fury.register::<Color>(999);
let color = Color::Red;
let bin = fury.serialize(&color);
let color2: Color = fury.deserialize(&bin).expect("");
assert_eq!(color, color2);
}

#[test]
fn complex_struct() {
#[derive(Fury, Debug, PartialEq, Default)]
Expand Down

0 comments on commit 57ce6bf

Please sign in to comment.