This is an automated email from the ASF dual-hosted git repository.

wangweipeng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fury.git


The following commit(s) were added to refs/heads/main by this push:
     new 0e18130b feat(Rust): Implement TypeMeta part of the compatibility 
features (#1789)
0e18130b is described below

commit 0e18130b9282e79595e756cf105cea028e4a3e77
Author: weipeng <[email protected]>
AuthorDate: Mon Aug 5 20:08:43 2024 +0800

    feat(Rust): Implement TypeMeta part of the compatibility features (#1789)
    
    ## What does this PR do?
    
    ### Refine code struct and implement some compatibility features
    1. Split fury_meta file into individual files, as the file is too large
    to be easily read. There are a lot of features should be implemented by
    macro, split it is necessary.
    2. Implement compatibility by the macro, which will now generate a
    pattern match expression.
    3. Write type meta to binary when serializing objects.
    4. Read type meta for the pattern match which is generated at compile
    time when deserializing.
    5. Replace lazy_static by Once for it has been stabled in stdlib
    
    ### Some unimplemented features
    1. Add a v-table for looking up generic methods by type_id, which is
    used for support the Any type.
    2. Support draining unused binary data when receiving an unregistered
    type.
---
 rust/fury-core/Cargo.toml                          |   4 +-
 rust/fury-core/src/buffer.rs                       |   4 +
 rust/fury-core/src/error.rs                        |   3 +
 rust/fury-core/src/fury.rs                         |  49 +++++--
 rust/fury-core/src/lib.rs                          |   4 +-
 rust/fury-core/src/meta/mod.rs                     |   2 -
 rust/fury-core/src/meta/type_meta.rs               |  88 ++++++++++---
 rust/fury-core/src/read_state.rs                   |  66 ----------
 rust/fury-core/src/resolver/context.rs             | 125 ++++++++++++++++++
 .../meta_store.rs => resolver/meta_resolver.rs}    |  54 ++++----
 rust/fury-core/src/{internal => resolver}/mod.rs   |  11 +-
 rust/fury-core/src/row/row.rs                      |   7 +-
 rust/fury-core/src/serializer.rs                   |  86 -------------
 .../fury-core/src/{internal => serializer}/bool.rs |  12 +-
 .../src/{internal => serializer}/datetime.rs       |  29 ++---
 .../fury-core/src/{internal => serializer}/list.rs |  18 +--
 rust/fury-core/src/{internal => serializer}/map.rs |  22 ++--
 rust/fury-core/src/serializer/mod.rs               |  91 +++++++++++++
 .../src/{internal => serializer}/number.rs         |  12 +-
 .../src/{internal => serializer}/option.rs         |  30 ++---
 .../src/{internal => serializer}/primitive_list.rs |  34 +++--
 rust/fury-core/src/{internal => serializer}/set.rs |  18 +--
 .../src/{internal => serializer}/string.rs         |  16 +--
 rust/fury-core/src/types.rs                        |   7 +-
 rust/fury-core/src/util.rs                         |   8 ++
 rust/fury-core/src/write_state.rs                  |  82 ------------
 rust/fury-derive/src/fury_meta.rs                  | 141 ---------------------
 rust/fury-derive/src/fury_row.rs                   |   3 +-
 rust/fury-derive/src/lib.rs                        |   8 +-
 rust/fury-derive/src/object/misc.rs                |  93 ++++++++++++++
 .../src/internal => fury-derive/src/object}/mod.rs |  15 +--
 rust/fury-derive/src/object/read.rs                | 108 ++++++++++++++++
 rust/fury-derive/src/object/serializer.rs          |  49 +++++++
 rust/fury-derive/src/object/write.rs               |  74 +++++++++++
 .../internal/mod.rs => fury-derive/src/util.rs}    |  16 +--
 rust/tests/Cargo.toml                              |   1 -
 rust/tests/tests/test_complex_struct.rs            |  11 +-
 37 files changed, 813 insertions(+), 588 deletions(-)

diff --git a/rust/fury-core/Cargo.toml b/rust/fury-core/Cargo.toml
index 3be240ff..5e8f8b77 100644
--- a/rust/fury-core/Cargo.toml
+++ b/rust/fury-core/Cargo.toml
@@ -25,10 +25,10 @@ rust-version.workspace = true
 proc-macro2 = { default-features = false, version = "1.0" }
 syn = { default-features = false, version = "2.0", features = ["full", "fold"] 
}
 quote = { default-features = false, version = "1.0" }
-lazy_static = { version = "1.4" }
 byteorder = { version = "1.4" }
 chrono = "0.4"
 thiserror = { default-features = false, version = "1.0" }
+num_enum = "0.5.1"
 
 
 [[bench]]
@@ -38,4 +38,4 @@ harness = false
 
 [dev-dependencies]
 criterion = "0.5.1"
-rand = "0.8.5"
\ No newline at end of file
+rand = "0.8.5"
diff --git a/rust/fury-core/src/buffer.rs b/rust/fury-core/src/buffer.rs
index 2ebf66b9..c81ec17f 100644
--- a/rust/fury-core/src/buffer.rs
+++ b/rust/fury-core/src/buffer.rs
@@ -238,6 +238,10 @@ impl<'bf> Reader<'bf> {
         self.move_next(len as usize);
     }
 
+    pub fn slice(&self) -> &[u8] {
+        self.bf
+    }
+
     pub fn bytes(&mut self, len: usize) -> &'bf [u8] {
         let result = &self.bf[self.cursor..self.cursor + len];
         self.move_next(len);
diff --git a/rust/fury-core/src/error.rs b/rust/fury-core/src/error.rs
index 717d18bf..a6fc9967 100644
--- a/rust/fury-core/src/error.rs
+++ b/rust/fury-core/src/error.rs
@@ -52,6 +52,9 @@ pub enum Error {
     #[error("Unsupported Language Code; receive: {code:?}")]
     UnsupportedLanguageCode { code: u8 },
 
+    #[error("Unsupported encoding of field name in type meta; receive: 
{code:?}")]
+    UnsupportedTypeMetaFieldNameEncoding { code: u8 },
+
     #[error("encoded_data cannot be empty")]
     EncodedDataEmpty,
 
diff --git a/rust/fury-core/src/fury.rs b/rust/fury-core/src/fury.rs
index 34a1532e..376374c9 100644
--- a/rust/fury-core/src/fury.rs
+++ b/rust/fury-core/src/fury.rs
@@ -17,10 +17,10 @@
 
 use crate::buffer::{Reader, Writer};
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
-use crate::types::Mode;
-use crate::write_state::WriteState;
+use crate::types::{config_flags, Language, Mode, SIZE_OF_REF_AND_TYPE};
 
 pub struct Fury {
     mode: Mode,
@@ -29,32 +29,57 @@ pub struct Fury {
 impl Default for Fury {
     fn default() -> Self {
         Fury {
-            mode: Mode::Compatible,
+            mode: Mode::SchemaConsistent,
         }
     }
 }
 
 impl Fury {
-    pub fn mode(&mut self, mode: Mode) {
+    pub fn mode(mut self, mode: Mode) -> Self {
         self.mode = mode;
+        self
     }
 
     pub fn get_mode(&self) -> &Mode {
         &self.mode
     }
 
+    pub fn write_head<T: Serializer>(&self, writer: &mut Writer) -> usize {
+        const HEAD_SIZE: usize = 10;
+        writer.reserve(<T as Serializer>::reserved_space() + 
SIZE_OF_REF_AND_TYPE + HEAD_SIZE);
+        let mut bitmap = 0;
+        bitmap |= config_flags::IS_LITTLE_ENDIAN_FLAG;
+        bitmap |= config_flags::IS_CROSS_LANGUAGE_FLAG;
+        writer.u8(bitmap);
+        writer.u8(Language::Rust as u8);
+        writer.skip(4); // meta offset
+        writer.len() - 4
+    }
+
+    fn read_head(&self, reader: &mut Reader) -> Result<u32, Error> {
+        let _bitmap = reader.u8();
+        let _language: Language = reader.u8().try_into()?;
+        Ok(reader.u32())
+    }
+
     pub fn deserialize<T: Serializer>(&self, bf: &[u8]) -> Result<T, Error> {
-        let reader = Reader::new(bf);
-        let mut deserializer = ReadState::new(self, reader);
-        deserializer.head()?;
-        <T as Serializer>::deserialize(&mut deserializer)
+        let mut reader = Reader::new(bf);
+        let meta_offset = self.read_head(&mut reader)?;
+        let mut context = ReadContext::new(self, reader);
+        if meta_offset > 0 {
+            context.load_meta(meta_offset as usize);
+        }
+        <T as Serializer>::deserialize(&mut context)
     }
 
     pub fn serialize<T: Serializer>(&self, record: &T) -> Vec<u8> {
         let mut writer = Writer::default();
-        let mut serializer = WriteState::new(self, &mut writer);
-        serializer.head::<T>();
-        <T as Serializer>::serialize(record, &mut serializer);
+        let meta_offset = self.write_head::<T>(&mut writer);
+        let mut context = WriteContext::new(self, &mut writer);
+        <T as Serializer>::serialize(record, &mut context);
+        if Mode::Compatible == self.mode {
+            context.write_meta(meta_offset);
+        }
         writer.dump()
     }
 }
diff --git a/rust/fury-core/src/lib.rs b/rust/fury-core/src/lib.rs
index 18e85d97..8ac31bc7 100644
--- a/rust/fury-core/src/lib.rs
+++ b/rust/fury-core/src/lib.rs
@@ -18,11 +18,9 @@
 pub mod buffer;
 pub mod error;
 pub mod fury;
-pub mod internal;
 pub mod meta;
-pub mod read_state;
+pub mod resolver;
 pub mod row;
 pub mod serializer;
 pub mod types;
 pub mod util;
-pub mod write_state;
diff --git a/rust/fury-core/src/meta/mod.rs b/rust/fury-core/src/meta/mod.rs
index 58a81ea0..bf0ba4bf 100644
--- a/rust/fury-core/src/meta/mod.rs
+++ b/rust/fury-core/src/meta/mod.rs
@@ -15,11 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-mod meta_store;
 mod meta_string;
 mod string_util;
 mod type_meta;
 
-pub use meta_store::{MetaReaderStore, MetaWriterStore};
 pub use meta_string::{Encoding, MetaString, MetaStringDecoder, 
MetaStringEncoder};
 pub use type_meta::{FieldInfo, TypeMeta};
diff --git a/rust/fury-core/src/meta/type_meta.rs 
b/rust/fury-core/src/meta/type_meta.rs
index 99ac37bd..f7f781df 100644
--- a/rust/fury-core/src/meta/type_meta.rs
+++ b/rust/fury-core/src/meta/type_meta.rs
@@ -18,12 +18,12 @@
 use super::meta_string::MetaStringEncoder;
 use crate::buffer::{Reader, Writer};
 use crate::error::Error;
+use crate::meta::{Encoding, MetaStringDecoder};
 use crate::types::FieldType;
 
 //todo backward/forward compatibility
 #[allow(dead_code)]
 pub struct FieldInfo {
-    tag_id: u32,
     field_name: String,
     field_type: FieldType,
 }
@@ -33,7 +33,34 @@ impl FieldInfo {
         FieldInfo {
             field_name: field_name.to_string(),
             field_type,
-            tag_id: 0,
+        }
+    }
+
+    fn u8_to_encoding(value: u8) -> Result<Encoding, Error> {
+        match value {
+            0x00 => Ok(Encoding::Utf8),
+            0x01 => Ok(Encoding::AllToLowerSpecial),
+            0x02 => Ok(Encoding::LowerUpperDigitSpecial),
+            _ => Err(Error::UnsupportedTypeMetaFieldNameEncoding { code: value 
}),
+        }
+    }
+
+    fn from_bytes(reader: &mut Reader) -> FieldInfo {
+        let header = reader.u8();
+        let encoding = Self::u8_to_encoding((header & 0b11000) >> 3).unwrap();
+        let mut size = (header & 0b11100000) as i32 >> 5;
+        size = if size == 0b111 {
+            reader.var_int32() + 7
+        } else {
+            size
+        };
+        let type_id = reader.i16();
+        let field_name = MetaStringDecoder::new()
+            .decode(reader.bytes(size as usize), encoding)
+            .unwrap();
+        FieldInfo {
+            field_name,
+            field_type: FieldType::try_from(type_id).unwrap(),
         }
     }
 
@@ -42,7 +69,7 @@ impl FieldInfo {
         let meta_string = MetaStringEncoder::new().encode(&self.field_name)?;
         let mut header = 1 << 2;
         let encoded = meta_string.bytes.as_slice();
-        let size = (encoded.len() - 1) as u32;
+        let size = encoded.len() as u32;
         header |= (meta_string.encoding as u8) << 3;
         let big_size = size >= 7;
         if big_size {
@@ -53,17 +80,29 @@ impl FieldInfo {
             header |= (size << 5) as u8;
             writer.u8(header);
         }
+        writer.i16(self.field_type as i16);
         writer.bytes(encoded);
         Ok(writer.dump())
     }
 }
 
-struct TypeMetaLayer {
+pub struct TypeMetaLayer {
     type_id: u32,
     field_info: Vec<FieldInfo>,
 }
 
 impl TypeMetaLayer {
+    pub fn new(type_id: u32, field_info: Vec<FieldInfo>) -> TypeMetaLayer {
+        TypeMetaLayer {
+            type_id,
+            field_info,
+        }
+    }
+
+    pub fn get_field_info(&self) -> &Vec<FieldInfo> {
+        &self.field_info
+    }
+
     fn to_bytes(&self) -> Result<Vec<u8>, Error> {
         let mut writer = Writer::default();
         writer.var_int32(self.field_info.len() as i32);
@@ -73,6 +112,15 @@ impl TypeMetaLayer {
         }
         Ok(writer.dump())
     }
+
+    fn from_bytes(reader: &mut Reader) -> TypeMetaLayer {
+        let field_num = reader.var_int32();
+        let type_id = reader.var_int32() as u32;
+        let field_info = (0..field_num)
+            .map(|_| FieldInfo::from_bytes(reader))
+            .collect();
+        TypeMetaLayer::new(type_id, field_info)
+    }
 }
 
 pub struct TypeMeta {
@@ -81,33 +129,33 @@ pub struct TypeMeta {
 }
 
 impl TypeMeta {
+    pub fn get_field_info(&self) -> &Vec<FieldInfo> {
+        self.layers.first().unwrap().get_field_info()
+    }
+
     pub fn from_fields(type_id: u32, field_info: Vec<FieldInfo>) -> TypeMeta {
         TypeMeta {
             hash: 0,
-            layers: vec![TypeMetaLayer {
-                type_id,
-                field_info,
-            }],
+            layers: vec![TypeMetaLayer::new(type_id, field_info)],
         }
     }
 
+    pub fn from_bytes(reader: &mut Reader) -> TypeMeta {
+        let header = reader.u64();
+        let hash = header >> 8; // high 56bits indicate hash
+        let layer_count = header & 0b1111; // class count
+        let layers: Vec<TypeMetaLayer> = (0..layer_count)
+            .map(|_| TypeMetaLayer::from_bytes(reader))
+            .collect();
+        TypeMeta { hash, layers }
+    }
+
     pub fn to_bytes(&self) -> Result<Vec<u8>, Error> {
         let mut writer = Writer::default();
-        writer.u64((self.hash << 4) | (self.layers.len() as u64 & 0b1111));
+        writer.u64((self.hash << 8) | (self.layers.len() as u64 & 0b1111));
         for layer in self.layers.iter() {
             writer.bytes(layer.to_bytes()?.as_slice());
         }
         Ok(writer.dump())
     }
-
-    pub fn read_hash_from_bytes(reader: &mut Reader) -> u64 {
-        reader.u64() >> 7
-    }
-
-    pub fn from_bytes(_reader: &mut Reader) -> TypeMeta {
-        TypeMeta {
-            hash: 0,
-            layers: Vec::new(),
-        }
-    }
 }
diff --git a/rust/fury-core/src/read_state.rs b/rust/fury-core/src/read_state.rs
deleted file mode 100644
index eaffdaa4..00000000
--- a/rust/fury-core/src/read_state.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use super::buffer::Reader;
-use super::types::Language;
-use crate::error::Error;
-use crate::fury::Fury;
-
-pub struct ReadState<'de, 'bf: 'de> {
-    pub reader: Reader<'bf>,
-    pub tags: Vec<&'de str>,
-    pub fury: &'de Fury,
-}
-
-impl<'de, 'bf: 'de> ReadState<'de, 'bf> {
-    pub fn new(fury: &'de Fury, reader: Reader<'bf>) -> ReadState<'de, 'bf> {
-        ReadState {
-            reader,
-            tags: Vec::new(),
-            fury,
-        }
-    }
-
-    pub fn get_fury(&self) -> &Fury {
-        self.fury
-    }
-
-    pub fn head(&mut self) -> Result<(), Error> {
-        let _bitmap = self.reader.u8();
-        let _language: Language = self.reader.u8().try_into()?;
-        self.reader.skip(8); // native offset and size
-        Ok(())
-    }
-
-    pub fn read_tag(&mut self) -> Result<&str, Error> {
-        const USESTRINGVALUE: u8 = 0;
-        const USESTRINGID: u8 = 1;
-        let tag_type = self.reader.u8();
-        if tag_type == USESTRINGID {
-            Ok(self.tags[self.reader.i16() as usize])
-        } else if tag_type == USESTRINGVALUE {
-            self.reader.skip(8); // todo tag hash
-            let len = self.reader.i16();
-            let tag: &str =
-                unsafe { std::str::from_utf8_unchecked(self.reader.bytes(len 
as usize)) };
-            self.tags.push(tag);
-            Ok(tag)
-        } else {
-            Err(Error::TagType(tag_type))
-        }
-    }
-}
diff --git a/rust/fury-core/src/resolver/context.rs 
b/rust/fury-core/src/resolver/context.rs
new file mode 100644
index 00000000..ab24ed41
--- /dev/null
+++ b/rust/fury-core/src/resolver/context.rs
@@ -0,0 +1,125 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::buffer::{Reader, Writer};
+use crate::error::Error;
+use crate::fury::Fury;
+
+use crate::meta::TypeMeta;
+use crate::resolver::meta_resolver::{MetaReaderResolver, MetaWriterResolver};
+use std::any::TypeId;
+use std::rc::Rc;
+
+pub struct WriteContext<'se> {
+    pub writer: &'se mut Writer,
+    pub tags: Vec<&'static str>,
+    fury: &'se Fury,
+    meta_resolver: MetaWriterResolver<'se>,
+}
+
+impl<'se> WriteContext<'se> {
+    pub fn new(fury: &'se Fury, writer: &'se mut Writer) -> WriteContext<'se> {
+        WriteContext {
+            writer,
+            tags: Vec::new(),
+            fury,
+            meta_resolver: MetaWriterResolver::default(),
+        }
+    }
+
+    pub fn push_meta(&mut self, type_id: TypeId, type_def: &'static [u8]) -> 
usize {
+        self.meta_resolver.push(type_id, type_def)
+    }
+
+    pub fn write_meta(&mut self, offset: usize) {
+        self.writer
+            .set_bytes(offset, &(self.writer.len() as u32).to_le_bytes());
+        self.meta_resolver.to_bytes(self.writer).unwrap()
+    }
+
+    pub fn get_fury(&self) -> &Fury {
+        self.fury
+    }
+
+    pub fn write_tag(&mut self, tag: &'static str) {
+        const USESTRINGVALUE: u8 = 0;
+        const USESTRINGID: u8 = 1;
+
+        let mayby_idx = self.tags.iter().position(|x| *x == tag);
+        match mayby_idx {
+            Some(idx) => {
+                self.writer.u8(USESTRINGID);
+                self.writer.i16(idx as i16);
+            }
+            None => {
+                self.writer.u8(USESTRINGVALUE);
+                self.writer.skip(8); // todo tag hash
+                self.writer.i16(tag.len() as i16);
+                self.writer.bytes(tag.as_bytes());
+            }
+        };
+    }
+}
+
+pub struct ReadContext<'de, 'bf: 'de> {
+    pub reader: Reader<'bf>,
+    pub tags: Vec<&'de str>,
+    pub fury: &'de Fury,
+    pub meta_resolver: MetaReaderResolver,
+}
+
+impl<'de, 'bf: 'de> ReadContext<'de, 'bf> {
+    pub fn new(fury: &'de Fury, reader: Reader<'bf>) -> ReadContext<'de, 'bf> {
+        ReadContext {
+            reader,
+            tags: Vec::new(),
+            fury,
+            meta_resolver: MetaReaderResolver::default(),
+        }
+    }
+
+    pub fn get_fury(&self) -> &Fury {
+        self.fury
+    }
+
+    pub fn get_meta(&self, type_index: usize) -> &Rc<TypeMeta> {
+        self.meta_resolver.get(type_index)
+    }
+
+    pub fn load_meta(&mut self, offset: usize) {
+        self.meta_resolver
+            .load(&mut Reader::new(&self.reader.slice()[offset..]))
+    }
+
+    pub fn read_tag(&mut self) -> Result<&str, Error> {
+        const USESTRINGVALUE: u8 = 0;
+        const USESTRINGID: u8 = 1;
+        let tag_type = self.reader.u8();
+        if tag_type == USESTRINGID {
+            Ok(self.tags[self.reader.i16() as usize])
+        } else if tag_type == USESTRINGVALUE {
+            self.reader.skip(8); // todo tag hash
+            let len = self.reader.i16();
+            let tag: &str =
+                unsafe { std::str::from_utf8_unchecked(self.reader.bytes(len 
as usize)) };
+            self.tags.push(tag);
+            Ok(tag)
+        } else {
+            Err(Error::TagType(tag_type))
+        }
+    }
+}
diff --git a/rust/fury-core/src/meta/meta_store.rs 
b/rust/fury-core/src/resolver/meta_resolver.rs
similarity index 52%
rename from rust/fury-core/src/meta/meta_store.rs
rename to rust/fury-core/src/resolver/meta_resolver.rs
index 5cc4149d..d39eea6e 100644
--- a/rust/fury-core/src/meta/meta_store.rs
+++ b/rust/fury-core/src/resolver/meta_resolver.rs
@@ -18,63 +18,59 @@
 use crate::buffer::{Reader, Writer};
 use crate::error::Error;
 use crate::meta::TypeMeta;
+use std::any::TypeId;
 use std::collections::HashMap;
+use std::rc::Rc;
 
-#[allow(dead_code)]
-pub struct MetaReaderStore {
-    reading_type_defs: Vec<TypeMeta>,
+#[derive(Default)]
+pub struct MetaReaderResolver {
+    reading_type_defs: Vec<Rc<TypeMeta>>,
 }
 
-#[allow(dead_code)]
-impl MetaReaderStore {
-    fn new() -> MetaReaderStore {
-        MetaReaderStore {
-            reading_type_defs: Vec::new(),
-        }
-    }
-
-    fn get(&self, index: usize) -> &TypeMeta {
+impl MetaReaderResolver {
+    pub fn get(&self, index: usize) -> &Rc<TypeMeta> {
         unsafe { self.reading_type_defs.get_unchecked(index) }
     }
 
-    fn from_bytes(reader: &mut Reader) -> MetaReaderStore {
+    pub fn load(&mut self, reader: &mut Reader) {
         let meta_size = reader.var_int32();
-        let mut reading_type_defs = Vec::<TypeMeta>::with_capacity(meta_size 
as usize);
+        self.reading_type_defs.reserve(meta_size as usize);
         for _ in 0..meta_size {
-            reading_type_defs.push(TypeMeta::from_bytes(reader));
+            self.reading_type_defs
+                .push(Rc::new(TypeMeta::from_bytes(reader)));
         }
-        MetaReaderStore { reading_type_defs }
     }
 }
 
 #[derive(Default)]
-pub struct MetaWriterStore<'a> {
-    writing_type_defs: Vec<&'a [u8]>,
-    index_map: HashMap<u32, usize>,
+pub struct MetaWriterResolver<'a> {
+    type_defs: Vec<&'a [u8]>,
+    type_id_index_map: HashMap<TypeId, usize>,
 }
 
 #[allow(dead_code)]
-impl<'a> MetaWriterStore<'a> {
-    pub fn push<'b: 'a>(&mut self, type_id: u32, type_meta_bytes: &'b [u8]) -> 
usize {
-        match self.index_map.get(&type_id) {
+impl<'a> MetaWriterResolver<'a> {
+    pub fn push<'b: 'a>(&mut self, type_id: TypeId, type_meta_bytes: &'b [u8]) 
-> usize {
+        match self.type_id_index_map.get(&type_id) {
             None => {
-                let index = self.writing_type_defs.len();
-                self.writing_type_defs.push(type_meta_bytes);
-                self.index_map.insert(type_id, index);
+                let index = self.type_defs.len();
+                self.type_defs.push(type_meta_bytes);
+                self.type_id_index_map.insert(type_id, index);
                 index
             }
             Some(index) => *index,
         }
     }
 
-    fn to_bytes(&self, writer: &mut Writer) -> Result<(), Error> {
-        for item in self.writing_type_defs.iter() {
+    pub fn to_bytes(&self, writer: &mut Writer) -> Result<(), Error> {
+        writer.var_int32(self.type_defs.len() as i32);
+        for item in self.type_defs.iter() {
             writer.bytes(item)
         }
         Ok(())
     }
 
-    fn reset(&mut self) {
-        self.writing_type_defs.clear();
+    pub fn reset(&mut self) {
+        self.type_defs.clear();
     }
 }
diff --git a/rust/fury-core/src/internal/mod.rs 
b/rust/fury-core/src/resolver/mod.rs
similarity index 88%
copy from rust/fury-core/src/internal/mod.rs
copy to rust/fury-core/src/resolver/mod.rs
index 4b4db5d5..ac511400 100644
--- a/rust/fury-core/src/internal/mod.rs
+++ b/rust/fury-core/src/resolver/mod.rs
@@ -15,12 +15,5 @@
 // specific language governing permissions and limitations
 // under the License.
 
-mod bool;
-mod datetime;
-mod list;
-mod map;
-mod number;
-mod option;
-mod primitive_list;
-mod set;
-mod string;
+pub mod context;
+pub mod meta_resolver;
diff --git a/rust/fury-core/src/row/row.rs b/rust/fury-core/src/row/row.rs
index baeb33f5..f9e995b1 100644
--- a/rust/fury-core/src/row/row.rs
+++ b/rust/fury-core/src/row/row.rs
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use crate::util::EPOCH;
 use crate::{buffer::Writer, error::Error};
 use byteorder::{ByteOrder, LittleEndian};
 use chrono::{DateTime, Days, NaiveDate, NaiveDateTime};
@@ -84,15 +85,11 @@ impl<'a> Row<'a> for bool {
     }
 }
 
-lazy_static::lazy_static!(
-    static ref EPOCH: NaiveDate = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
-);
-
 impl<'a> Row<'a> for NaiveDate {
     type ReadResult = Result<NaiveDate, Error>;
 
     fn write(v: &Self, writer: &mut Writer) {
-        let days_since_epoch = v.signed_duration_since(*EPOCH).num_days();
+        let days_since_epoch = v.signed_duration_since(EPOCH).num_days();
         writer.u32(days_since_epoch as u32);
     }
 
diff --git a/rust/fury-core/src/serializer.rs b/rust/fury-core/src/serializer.rs
deleted file mode 100644
index a5d4f8a7..00000000
--- a/rust/fury-core/src/serializer.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use crate::error::Error;
-use crate::read_state::ReadState;
-use crate::types::{FieldType, RefFlag};
-use crate::write_state::WriteState;
-
-pub trait Serializer
-where
-    Self: Sized,
-{
-    /// The fixed memory size of the Type.
-    /// Avoid the memory check, which would hurt performance.
-    fn reserved_space() -> usize;
-
-    /// Write the data into the buffer.
-    fn write(&self, serializer: &mut WriteState);
-
-    /// Entry point of the serialization.
-    ///
-    /// Step 1: write the type flag and type flag into the buffer.
-    /// Step 2: invoke the write function to write the Rust object.
-    fn serialize(&self, serializer: &mut WriteState) {
-        // ref flag
-        serializer.writer.i8(RefFlag::NotNullValue as i8);
-        // type
-        serializer.writer.i16(Self::ty() as i16);
-        self.write(serializer);
-    }
-
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error>;
-
-    fn deserialize(deserializer: &mut ReadState) -> Result<Self, Error> {
-        // ref flag
-        let ref_flag = deserializer.reader.i8();
-
-        if ref_flag == (RefFlag::NotNullValue as i8) || ref_flag == 
(RefFlag::RefValue as i8) {
-            // type_id
-            let type_id = deserializer.reader.i16();
-            let ty = Self::ty();
-            if type_id != ty as i16 {
-                Err(Error::FieldType {
-                    expected: ty,
-                    actial: type_id,
-                })
-            } else {
-                Ok(Self::read(deserializer)?)
-            }
-        } else if ref_flag == (RefFlag::Null as i8) {
-            Err(Error::Null)
-        } else if ref_flag == (RefFlag::Ref as i8) {
-            Err(Error::Ref)
-        } else {
-            Err(Error::BadRefFlag)
-        }
-    }
-
-    fn ty() -> FieldType;
-
-    fn hash() -> u32 {
-        0
-    }
-
-    fn tag() -> &'static str {
-        ""
-    }
-
-    fn type_def() -> &'static [u8] {
-        &[]
-    }
-}
diff --git a/rust/fury-core/src/internal/bool.rs 
b/rust/fury-core/src/serializer/bool.rs
similarity index 78%
rename from rust/fury-core/src/internal/bool.rs
rename to rust/fury-core/src/serializer/bool.rs
index edeebbd8..e3e631d3 100644
--- a/rust/fury-core/src/internal/bool.rs
+++ b/rust/fury-core/src/serializer/bool.rs
@@ -16,10 +16,10 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::FieldType;
-use crate::write_state::WriteState;
 use std::mem;
 
 impl Serializer for bool {
@@ -27,12 +27,12 @@ impl Serializer for bool {
         mem::size_of::<i32>()
     }
 
-    fn write(&self, serializer: &mut WriteState) {
-        serializer.writer.u8(if *self { 1 } else { 0 });
+    fn write(&self, context: &mut WriteContext) {
+        context.writer.u8(if *self { 1 } else { 0 });
     }
 
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
-        Ok(deserializer.reader.u8() == 1)
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
+        Ok(context.reader.u8() == 1)
     }
 
     fn ty() -> FieldType {
diff --git a/rust/fury-core/src/internal/datetime.rs 
b/rust/fury-core/src/serializer/datetime.rs
similarity index 70%
rename from rust/fury-core/src/internal/datetime.rs
rename to rust/fury-core/src/serializer/datetime.rs
index 8852a077..a1f42d72 100644
--- a/rust/fury-core/src/internal/datetime.rs
+++ b/rust/fury-core/src/serializer/datetime.rs
@@ -16,16 +16,17 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::{FieldType, FuryGeneralList};
-use crate::write_state::WriteState;
+use crate::util::EPOCH;
 use chrono::{DateTime, Days, NaiveDate, NaiveDateTime};
 use std::mem;
 
 impl Serializer for NaiveDateTime {
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
-        let timestamp = deserializer.reader.u64();
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
+        let timestamp = context.reader.u64();
         let ret = DateTime::from_timestamp_millis(timestamp as i64).map(|dt| 
dt.naive_utc());
         match ret {
             Some(r) => Ok(r),
@@ -33,10 +34,8 @@ impl Serializer for NaiveDateTime {
         }
     }
 
-    fn write(&self, serializer: &mut WriteState) {
-        serializer
-            .writer
-            .u64(self.and_utc().timestamp_millis() as u64);
+    fn write(&self, context: &mut WriteContext) {
+        context.writer.u64(self.and_utc().timestamp_millis() as u64);
     }
 
     fn reserved_space() -> usize {
@@ -50,22 +49,18 @@ impl Serializer for NaiveDateTime {
 
 impl FuryGeneralList for NaiveDateTime {}
 
-lazy_static::lazy_static!(
-    static ref EPOCH: NaiveDate = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
-);
-
 impl Serializer for NaiveDate {
-    fn write(&self, serializer: &mut WriteState) {
-        let days_since_epoch = self.signed_duration_since(*EPOCH).num_days();
-        serializer.writer.u64(days_since_epoch as u64);
+    fn write(&self, context: &mut WriteContext) {
+        let days_since_epoch = self.signed_duration_since(EPOCH).num_days();
+        context.writer.u64(days_since_epoch as u64);
     }
 
     fn reserved_space() -> usize {
         mem::size_of::<u64>()
     }
 
-    fn read(serializer: &mut ReadState) -> Result<Self, Error> {
-        let days = serializer.reader.u64();
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
+        let days = context.reader.u64();
         match EPOCH.checked_add_days(Days::new(days)) {
             Some(value) => Ok(value),
             None => Err(Error::NaiveDate),
diff --git a/rust/fury-core/src/internal/list.rs 
b/rust/fury-core/src/serializer/list.rs
similarity index 79%
rename from rust/fury-core/src/internal/list.rs
rename to rust/fury-core/src/serializer/list.rs
index 491e377b..233fe93f 100644
--- a/rust/fury-core/src/internal/list.rs
+++ b/rust/fury-core/src/serializer/list.rs
@@ -16,33 +16,33 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::{FieldType, FuryGeneralList, SIZE_OF_REF_AND_TYPE};
-use crate::write_state::WriteState;
 use std::mem;
 
 impl<T> Serializer for Vec<T>
 where
     T: Serializer + FuryGeneralList,
 {
-    fn write(&self, serializer: &mut WriteState) {
-        serializer.writer.var_int32(self.len() as i32);
-        serializer
+    fn write(&self, context: &mut WriteContext) {
+        context.writer.var_int32(self.len() as i32);
+        context
             .writer
             .reserve((<Self as Serializer>::reserved_space() + 
SIZE_OF_REF_AND_TYPE) * self.len());
         for item in self.iter() {
-            item.serialize(serializer);
+            item.serialize(context);
         }
     }
 
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
         // length
-        let len = deserializer.reader.var_int32();
+        let len = context.reader.var_int32();
         // value
         let mut result = Vec::new();
         for _ in 0..len {
-            result.push(T::deserialize(deserializer)?);
+            result.push(T::deserialize(context)?);
         }
         Ok(result)
     }
diff --git a/rust/fury-core/src/internal/map.rs 
b/rust/fury-core/src/serializer/map.rs
similarity index 76%
rename from rust/fury-core/src/internal/map.rs
rename to rust/fury-core/src/serializer/map.rs
index 791da121..d324a582 100644
--- a/rust/fury-core/src/internal/map.rs
+++ b/rust/fury-core/src/serializer/map.rs
@@ -16,39 +16,39 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::{FieldType, FuryGeneralList, SIZE_OF_REF_AND_TYPE};
-use crate::write_state::WriteState;
 use std::collections::HashMap;
 use std::mem;
 
 impl<T1: Serializer + Eq + std::hash::Hash, T2: Serializer> Serializer for 
HashMap<T1, T2> {
-    fn write(&self, serializer: &mut WriteState) {
+    fn write(&self, context: &mut WriteContext) {
         // length
-        serializer.writer.var_int32(self.len() as i32);
+        context.writer.var_int32(self.len() as i32);
 
         let reserved_space = (<T1 as Serializer>::reserved_space() + 
SIZE_OF_REF_AND_TYPE)
             * self.len()
             + (<T2 as Serializer>::reserved_space() + SIZE_OF_REF_AND_TYPE) * 
self.len();
-        serializer.writer.reserve(reserved_space);
+        context.writer.reserve(reserved_space);
 
         // key-value
         for i in self.iter() {
-            i.0.serialize(serializer);
-            i.1.serialize(serializer);
+            i.0.serialize(context);
+            i.1.serialize(context);
         }
     }
 
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
         // length
-        let len = deserializer.reader.var_int32();
+        let len = context.reader.var_int32();
         let mut result = HashMap::new();
         // key-value
         for _ in 0..len {
             result.insert(
-                <T1 as Serializer>::deserialize(deserializer)?,
-                <T2 as Serializer>::deserialize(deserializer)?,
+                <T1 as Serializer>::deserialize(context)?,
+                <T2 as Serializer>::deserialize(context)?,
             );
         }
         Ok(result)
diff --git a/rust/fury-core/src/serializer/mod.rs 
b/rust/fury-core/src/serializer/mod.rs
new file mode 100644
index 00000000..8a92c67b
--- /dev/null
+++ b/rust/fury-core/src/serializer/mod.rs
@@ -0,0 +1,91 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::error::Error;
+use crate::resolver::context::{ReadContext, WriteContext};
+use crate::types::{FieldType, RefFlag};
+
+mod bool;
+mod datetime;
+mod list;
+mod map;
+mod number;
+mod option;
+mod primitive_list;
+mod set;
+mod string;
+
+pub fn serialize<T: Serializer>(this: &T, context: &mut WriteContext) {
+    // ref flag
+    context.writer.i8(RefFlag::NotNullValue as i8);
+    // type
+    context.writer.i16(T::ty() as i16);
+    this.write(context);
+}
+
+pub fn deserialize<T: Serializer>(context: &mut ReadContext) -> Result<T, 
Error> {
+    // ref flag
+    let ref_flag = context.reader.i8();
+
+    if ref_flag == (RefFlag::NotNullValue as i8) || ref_flag == 
(RefFlag::RefValue as i8) {
+        // type_id
+        let type_id = context.reader.i16();
+        let ty = T::ty();
+        if type_id != ty as i16 {
+            Err(Error::FieldType {
+                expected: ty,
+                actial: type_id,
+            })
+        } else {
+            Ok(T::read(context)?)
+        }
+    } else if ref_flag == (RefFlag::Null as i8) {
+        Err(Error::Null)
+    } else if ref_flag == (RefFlag::Ref as i8) {
+        Err(Error::Ref)
+    } else {
+        Err(Error::BadRefFlag)
+    }
+}
+
+pub trait Serializer
+where
+    Self: Default,
+{
+    /// The fixed memory size of the Type.
+    /// Avoid the memory check, which would hurt performance.
+    fn reserved_space() -> usize;
+
+    /// Write the data into the buffer.
+    fn write(&self, context: &mut WriteContext);
+
+    /// Entry point of the serialization.
+    ///
+    /// Step 1: write the type flag and type flag into the buffer.
+    /// Step 2: invoke the write function to write the Rust object.
+    fn serialize(&self, context: &mut WriteContext) {
+        serialize(self, context);
+    }
+
+    fn read(context: &mut ReadContext) -> Result<Self, Error>;
+
+    fn deserialize(context: &mut ReadContext) -> Result<Self, Error> {
+        deserialize(context)
+    }
+
+    fn ty() -> FieldType;
+}
diff --git a/rust/fury-core/src/internal/number.rs 
b/rust/fury-core/src/serializer/number.rs
similarity index 87%
rename from rust/fury-core/src/internal/number.rs
rename to rust/fury-core/src/serializer/number.rs
index ef4f5083..4412007e 100644
--- a/rust/fury-core/src/internal/number.rs
+++ b/rust/fury-core/src/serializer/number.rs
@@ -16,10 +16,10 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::{FieldType, FuryGeneralList};
-use crate::write_state::WriteState;
 
 #[allow(dead_code)]
 fn to_u8_slice<T>(slice: &[T]) -> &[u8] {
@@ -30,12 +30,12 @@ fn to_u8_slice<T>(slice: &[T]) -> &[u8] {
 macro_rules! impl_num_serializer {
     ($name: ident, $ty:tt, $field_type: expr) => {
         impl Serializer for $ty {
-            fn write(&self, serializer: &mut WriteState) {
-                serializer.writer.$name(*self);
+            fn write(&self, context: &mut WriteContext) {
+                context.writer.$name(*self);
             }
 
-            fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
-                Ok(deserializer.reader.$name())
+            fn read(context: &mut ReadContext) -> Result<Self, Error> {
+                Ok(context.reader.$name())
             }
 
             fn reserved_space() -> usize {
diff --git a/rust/fury-core/src/internal/option.rs 
b/rust/fury-core/src/serializer/option.rs
similarity index 72%
rename from rust/fury-core/src/internal/option.rs
rename to rust/fury-core/src/serializer/option.rs
index d4f5b64e..023297f5 100644
--- a/rust/fury-core/src/internal/option.rs
+++ b/rust/fury-core/src/serializer/option.rs
@@ -16,23 +16,23 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::{FieldType, FuryGeneralList, RefFlag};
-use crate::write_state::WriteState;
 
 impl<T: Serializer> Serializer for Option<T> {
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
-        Ok(Some(T::read(deserializer)?))
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
+        Ok(Some(T::read(context)?))
     }
 
-    fn deserialize(deserializer: &mut ReadState) -> Result<Self, Error> {
+    fn deserialize(context: &mut ReadContext) -> Result<Self, Error> {
         // ref flag
-        let ref_flag = deserializer.reader.i8();
+        let ref_flag = context.reader.i8();
 
         if ref_flag == (RefFlag::NotNullValue as i8) || ref_flag == 
(RefFlag::RefValue as i8) {
             // type_id
-            let type_id = deserializer.reader.i16();
+            let type_id = context.reader.i16();
 
             if type_id != T::ty() as i16 {
                 Err(Error::FieldType {
@@ -40,7 +40,7 @@ impl<T: Serializer> Serializer for Option<T> {
                     actial: type_id,
                 })
             } else {
-                Ok(Some(T::read(deserializer)?))
+                Ok(Some(T::read(context)?))
             }
         } else if ref_flag == (RefFlag::Null as i8) {
             Ok(None)
@@ -51,26 +51,26 @@ impl<T: Serializer> Serializer for Option<T> {
         }
     }
 
-    fn write(&self, serializer: &mut WriteState) {
+    fn write(&self, context: &mut WriteContext) {
         if let Some(v) = self {
-            T::write(v, serializer)
+            T::write(v, context)
         } else {
             unreachable!("write should be call by serialize")
         }
     }
 
-    fn serialize(&self, serializer: &mut WriteState) {
+    fn serialize(&self, context: &mut WriteContext) {
         match self {
             Some(v) => {
                 // ref flag
-                serializer.writer.i8(RefFlag::NotNullValue as i8);
+                context.writer.i8(RefFlag::NotNullValue as i8);
                 // type
-                serializer.writer.i16(T::ty() as i16);
+                context.writer.i16(T::ty() as i16);
 
-                v.write(serializer);
+                v.write(context);
             }
             None => {
-                serializer.writer.i8(RefFlag::Null as i8);
+                context.writer.i8(RefFlag::Null as i8);
             }
         }
     }
diff --git a/rust/fury-core/src/internal/primitive_list.rs 
b/rust/fury-core/src/serializer/primitive_list.rs
similarity index 69%
rename from rust/fury-core/src/internal/primitive_list.rs
rename to rust/fury-core/src/serializer/primitive_list.rs
index f8ab7c3a..b033bb42 100644
--- a/rust/fury-core/src/internal/primitive_list.rs
+++ b/rust/fury-core/src/serializer/primitive_list.rs
@@ -16,10 +16,10 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::FieldType;
-use crate::write_state::WriteState;
 use std::mem;
 
 pub fn to_u8_slice<T>(slice: &[T]) -> &[u8] {
@@ -35,20 +35,16 @@ fn from_u8_slice<T: Clone>(slice: &[u8]) -> Vec<T> {
 macro_rules! impl_primitive_vec {
     ($name: ident, $ty:tt, $field_type: expr) => {
         impl Serializer for Vec<$ty> {
-            fn write(&self, serializer: &mut WriteState) {
-                serializer.writer.var_int32(self.len() as i32);
-                serializer
-                    .writer
-                    .reserve(self.len() * mem::size_of::<$ty>());
-                serializer.writer.bytes(to_u8_slice(self));
+            fn write(&self, context: &mut WriteContext) {
+                context.writer.var_int32(self.len() as i32);
+                context.writer.reserve(self.len() * mem::size_of::<$ty>());
+                context.writer.bytes(to_u8_slice(self));
             }
 
-            fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
+            fn read(context: &mut ReadContext) -> Result<Self, Error> {
                 // length
-                let len = (deserializer.reader.var_int32() as usize) * 
mem::size_of::<$ty>();
-                Ok(from_u8_slice::<$ty>(
-                    deserializer.reader.bytes(len as usize),
-                ))
+                let len = (context.reader.var_int32() as usize) * 
mem::size_of::<$ty>();
+                Ok(from_u8_slice::<$ty>(context.reader.bytes(len as usize)))
             }
 
             fn reserved_space() -> usize {
@@ -63,9 +59,9 @@ macro_rules! impl_primitive_vec {
 }
 
 impl Serializer for Vec<bool> {
-    fn write(&self, serializer: &mut WriteState) {
-        serializer.writer.var_int32(self.len() as i32);
-        serializer.writer.bytes(to_u8_slice(self));
+    fn write(&self, context: &mut WriteContext) {
+        context.writer.var_int32(self.len() as i32);
+        context.writer.bytes(to_u8_slice(self));
     }
 
     fn reserved_space() -> usize {
@@ -76,9 +72,9 @@ impl Serializer for Vec<bool> {
         FieldType::FuryPrimitiveBoolArray
     }
 
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
-        let size = deserializer.reader.var_int32();
-        let bytes = deserializer.reader.bytes(size as usize).to_vec();
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
+        let size = context.reader.var_int32();
+        let bytes = context.reader.bytes(size as usize).to_vec();
         Ok(unsafe { mem::transmute::<Vec<u8>, Vec<bool>>(bytes) })
     }
 }
diff --git a/rust/fury-core/src/internal/set.rs 
b/rust/fury-core/src/serializer/set.rs
similarity index 78%
rename from rust/fury-core/src/internal/set.rs
rename to rust/fury-core/src/serializer/set.rs
index 8989e6a2..a652dbd3 100644
--- a/rust/fury-core/src/internal/set.rs
+++ b/rust/fury-core/src/serializer/set.rs
@@ -16,35 +16,35 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::{FieldType, FuryGeneralList, SIZE_OF_REF_AND_TYPE};
-use crate::write_state::WriteState;
 use std::collections::HashSet;
 use std::mem;
 
 impl<T: Serializer + Eq + std::hash::Hash> Serializer for HashSet<T> {
-    fn write(&self, serializer: &mut WriteState) {
+    fn write(&self, context: &mut WriteContext) {
         // length
-        serializer.writer.i32(self.len() as i32);
+        context.writer.i32(self.len() as i32);
 
         let reserved_space =
             (<T as Serializer>::reserved_space() + SIZE_OF_REF_AND_TYPE) * 
self.len();
-        serializer.writer.reserve(reserved_space);
+        context.writer.reserve(reserved_space);
 
         // key-value
         for i in self.iter() {
-            i.serialize(serializer);
+            i.serialize(context);
         }
     }
 
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
         // length
-        let len = deserializer.reader.var_int32();
+        let len = context.reader.var_int32();
         let mut result = HashSet::new();
         // key-value
         for _ in 0..len {
-            result.insert(<T as Serializer>::deserialize(deserializer)?);
+            result.insert(<T as Serializer>::deserialize(context)?);
         }
         Ok(result)
     }
diff --git a/rust/fury-core/src/internal/string.rs 
b/rust/fury-core/src/serializer/string.rs
similarity index 74%
rename from rust/fury-core/src/internal/string.rs
rename to rust/fury-core/src/serializer/string.rs
index fc473b14..64190fa2 100644
--- a/rust/fury-core/src/internal/string.rs
+++ b/rust/fury-core/src/serializer/string.rs
@@ -16,10 +16,10 @@
 // under the License.
 
 use crate::error::Error;
-use crate::read_state::ReadState;
+use crate::resolver::context::ReadContext;
+use crate::resolver::context::WriteContext;
 use crate::serializer::Serializer;
 use crate::types::{FieldType, FuryGeneralList};
-use crate::write_state::WriteState;
 use std::mem;
 
 impl Serializer for String {
@@ -27,14 +27,14 @@ impl Serializer for String {
         mem::size_of::<i32>()
     }
 
-    fn write(&self, serializer: &mut WriteState) {
-        serializer.writer.var_int32(self.len() as i32);
-        serializer.writer.bytes(self.as_bytes());
+    fn write(&self, context: &mut WriteContext) {
+        context.writer.var_int32(self.len() as i32);
+        context.writer.bytes(self.as_bytes());
     }
 
-    fn read(deserializer: &mut ReadState) -> Result<Self, Error> {
-        let len = deserializer.reader.var_int32();
-        Ok(deserializer.reader.string(len as usize))
+    fn read(context: &mut ReadContext) -> Result<Self, Error> {
+        let len = context.reader.var_int32();
+        Ok(context.reader.string(len as usize))
     }
 
     fn ty() -> FieldType {
diff --git a/rust/fury-core/src/types.rs b/rust/fury-core/src/types.rs
index 47f6cf57..c1ba2b1f 100644
--- a/rust/fury-core/src/types.rs
+++ b/rust/fury-core/src/types.rs
@@ -16,6 +16,7 @@
 // under the License.
 
 use crate::error::Error;
+use num_enum::TryFromPrimitive;
 use std::mem;
 
 #[allow(dead_code)]
@@ -24,6 +25,8 @@ pub enum StringFlag {
     UTF8 = 1,
 }
 
+#[derive(TryFromPrimitive)]
+#[repr(i8)]
 pub enum RefFlag {
     Null = -3,
     // Ref indicates that object is a not-null value.
@@ -35,7 +38,8 @@ pub enum RefFlag {
     RefValue = 0,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq, TryFromPrimitive)]
+#[repr(i16)]
 pub enum FieldType {
     BOOL = 1,
     UINT8 = 2,
@@ -140,6 +144,7 @@ pub enum Language {
     Rust = 6,
 }
 
+#[derive(PartialEq)]
 pub enum Mode {
     SchemaConsistent,
     Compatible,
diff --git a/rust/fury-core/src/util.rs b/rust/fury-core/src/util.rs
index 0713e39e..31194cef 100644
--- a/rust/fury-core/src/util.rs
+++ b/rust/fury-core/src/util.rs
@@ -15,8 +15,16 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use chrono::NaiveDate;
 use std::ptr;
 
+pub const EPOCH: NaiveDate = match NaiveDate::from_ymd_opt(1970, 1, 1) {
+    None => {
+        panic!("Unreachable code")
+    }
+    Some(epoch) => epoch,
+};
+
 // Swapping the high 8 bits and the low 8 bits of a 16-bit value
 fn swap_endian(value: u16) -> u16 {
     (value << 8) | (value >> 8)
diff --git a/rust/fury-core/src/write_state.rs 
b/rust/fury-core/src/write_state.rs
deleted file mode 100644
index 9a756000..00000000
--- a/rust/fury-core/src/write_state.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use super::buffer::Writer;
-use super::types::{config_flags, Language, SIZE_OF_REF_AND_TYPE};
-use crate::fury::Fury;
-use crate::meta::MetaWriterStore;
-use crate::serializer::Serializer;
-
-pub struct WriteState<'se> {
-    pub writer: &'se mut Writer,
-    pub tags: Vec<&'static str>,
-    fury: &'se Fury,
-    meta_store: MetaWriterStore<'se>,
-}
-
-impl<'se> WriteState<'se> {
-    pub fn new(fury: &'se Fury, writer: &'se mut Writer) -> WriteState<'se> {
-        WriteState {
-            writer,
-            tags: Vec::new(),
-            fury,
-            meta_store: MetaWriterStore::default(),
-        }
-    }
-
-    pub fn push_meta(&mut self, type_id: u32, type_def: &'static [u8]) {
-        self.meta_store.push(type_id, type_def);
-    }
-
-    pub fn get_fury(&self) -> &Fury {
-        self.fury
-    }
-
-    pub fn write_tag(&mut self, tag: &'static str) {
-        const USESTRINGVALUE: u8 = 0;
-        const USESTRINGID: u8 = 1;
-
-        let mayby_idx = self.tags.iter().position(|x| *x == tag);
-        match mayby_idx {
-            Some(idx) => {
-                self.writer.u8(USESTRINGID);
-                self.writer.i16(idx as i16);
-            }
-            None => {
-                self.writer.u8(USESTRINGVALUE);
-                self.writer.skip(8); // todo tag hash
-                self.writer.i16(tag.len() as i16);
-                self.writer.bytes(tag.as_bytes());
-            }
-        };
-    }
-
-    pub fn head<T: Serializer>(&mut self) -> &Self {
-        const HEAD_SIZE: usize = 10;
-        self.writer
-            .reserve(<T as Serializer>::reserved_space() + 
SIZE_OF_REF_AND_TYPE + HEAD_SIZE);
-
-        let mut bitmap = 0;
-        bitmap |= config_flags::IS_LITTLE_ENDIAN_FLAG;
-        bitmap |= config_flags::IS_CROSS_LANGUAGE_FLAG;
-        self.writer.u8(bitmap);
-        self.writer.u8(Language::Rust as u8);
-        self.writer.skip(4); // native offset
-        self.writer.skip(4); // native size
-        self
-    }
-}
diff --git a/rust/fury-derive/src/fury_meta.rs 
b/rust/fury-derive/src/fury_meta.rs
deleted file mode 100644
index 47510998..00000000
--- a/rust/fury-derive/src/fury_meta.rs
+++ /dev/null
@@ -1,141 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use proc_macro::TokenStream;
-use quote::quote;
-use syn::{Field, Fields};
-
-pub fn sorted_fields(fields: &Fields) -> Vec<&Field> {
-    let mut fields = fields.iter().collect::<Vec<&Field>>();
-    fields.sort_by(|a, b| a.ident.cmp(&b.ident));
-    fields
-}
-
-pub fn derive_serializer(ast: &syn::DeriveInput, tag: &String) -> TokenStream {
-    let name = &ast.ident;
-    let fields = match &ast.data {
-        syn::Data::Struct(s) => sorted_fields(&s.fields),
-        _ => {
-            panic!("only struct be supported")
-        }
-    };
-
-    let name_hash: proc_macro2::Ident =
-        syn::Ident::new(&format!("HASH_{}", name).to_uppercase(), name.span());
-
-    let field_infos = fields.iter().map(|field| {
-        let ty = &field.ty;
-        let name = format!("{}", field.ident.as_ref().expect("should be field 
name"));
-        quote! {
-            fury_core::meta::FieldInfo::new(#name, <#ty as 
fury_core::serializer::Serializer>::ty())
-        }
-    });
-
-    let accessor_exprs = fields.iter().map(|field| {
-        let ty = &field.ty;
-        let ident = &field.ident;
-        quote! {
-            <#ty as 
fury_core::serializer::Serializer>::serialize(&self.#ident, serializer);
-        }
-    });
-
-    let reserved_size_exprs = fields.iter().map(|field| {
-        let ty = &field.ty;
-        // each field have one byte ref tag and two byte type id
-        quote! {
-            <#ty as fury_core::serializer::Serializer>::reserved_space() + 
fury_core::types::SIZE_OF_REF_AND_TYPE
-        }
-    });
-
-    let tag_bytelen = format!("{}", name).len();
-
-    let exprs = fields.iter().map(|field| {
-        let ty = &field.ty;
-        let ident = &field.ident;
-        quote! {
-            #ident: <#ty as 
fury_core::serializer::Serializer>::deserialize(state)?
-        }
-    });
-
-    let props = fields.iter().map(|field| {
-        let ty = &field.ty;
-        let name = format!("{}", field.ident.as_ref().expect("should be field 
name"));
-        quote! {
-            (#name, <#ty as fury_core::serializer::Serializer>::ty())
-        }
-    });
-
-    let gen = quote! {
-        impl fury_core::types::FuryGeneralList for #name {}
-        impl fury_core::serializer::Serializer for #name {
-            fn tag() -> &'static str {
-                #tag
-            }
-
-            fn hash() -> u32 {
-                lazy_static::lazy_static! {
-                    static ref #name_hash: u32 = 
fury_core::types::compute_struct_hash(vec![#(#props),*]);
-                }
-                *(#name_hash)
-            }
-
-            fn type_def() -> &'static [u8] {
-                lazy_static::lazy_static! {
-                    static ref type_definition: Vec<u8> = 
fury_core::meta::TypeMeta::from_fields(
-                        0,
-                        vec![#(#field_infos),*]
-                    ).to_bytes().unwrap();
-                }
-                type_definition.as_slice()
-            }
-
-            fn ty() -> fury_core::types::FieldType {
-                fury_core::types::FieldType::FuryTypeTag
-            }
-
-            fn write(&self, serializer: &mut 
fury_core::write_state::WriteState) {
-                // write tag string
-                serializer.write_tag(<#name as 
fury_core::serializer::Serializer>::tag());
-                // write tag hash
-                serializer.writer.u32(<#name as 
fury_core::serializer::Serializer>::hash());
-                // write fields
-                #(#accessor_exprs)*
-            }
-
-            fn read(state: &mut fury_core::read_state::ReadState) -> 
Result<Self, fury_core::error::Error> {
-                // read tag string
-                state.read_tag()?;
-                // read tag hash
-                let hash = state.reader.u32();
-                let expected = <#name as 
fury_core::serializer::Serializer>::hash();
-                if(hash != expected) {
-                    Err(fury_core::error::Error::StructHash{ expected, actial: 
hash })
-                } else {
-                    Ok(Self {
-                        #(#exprs),*
-                    })
-                }
-            }
-
-            fn reserved_space() -> usize {
-                // struct have four byte hash
-                #tag_bytelen + 4 + #(#reserved_size_exprs)+*
-            }
-        }
-    };
-    gen.into()
-}
diff --git a/rust/fury-derive/src/fury_row.rs b/rust/fury-derive/src/fury_row.rs
index 20b55aea..469f023d 100644
--- a/rust/fury-derive/src/fury_row.rs
+++ b/rust/fury-derive/src/fury_row.rs
@@ -15,11 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use crate::util::sorted_fields;
 use proc_macro::TokenStream;
 use quote::quote;
 
-use crate::fury_meta::sorted_fields;
-
 pub fn derive_row(ast: &syn::DeriveInput) -> TokenStream {
     let name = &ast.ident;
     let fields = match &ast.data {
diff --git a/rust/fury-derive/src/lib.rs b/rust/fury-derive/src/lib.rs
index a72e7a42..a9f2605b 100644
--- a/rust/fury-derive/src/lib.rs
+++ b/rust/fury-derive/src/lib.rs
@@ -15,16 +15,16 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use fury_meta::derive_serializer;
 use fury_row::derive_row;
 use proc_macro::TokenStream;
 use syn::{parse_macro_input, DeriveInput};
 
-mod fury_meta;
 mod fury_row;
+mod object;
+mod util;
 
 #[proc_macro_derive(Fury, attributes(tag))]
-pub fn proc_macro_derive_fury_meta(input: proc_macro::TokenStream) -> 
TokenStream {
+pub fn proc_macro_derive_fury_object(input: proc_macro::TokenStream) -> 
TokenStream {
     let input = parse_macro_input!(input as DeriveInput);
     let tag = input
         .attrs
@@ -38,7 +38,7 @@ pub fn proc_macro_derive_fury_meta(input: 
proc_macro::TokenStream) -> TokenStrea
             panic!("tag should be string")
         }
     };
-    derive_serializer(&input, &tag)
+    object::derive_serializer(&input, &tag)
 }
 
 #[proc_macro_derive(FuryRow)]
diff --git a/rust/fury-derive/src/object/misc.rs 
b/rust/fury-derive/src/object/misc.rs
new file mode 100644
index 00000000..a9416e2d
--- /dev/null
+++ b/rust/fury-derive/src/object/misc.rs
@@ -0,0 +1,93 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::Field;
+
+fn hash(fields: &[&Field]) -> TokenStream {
+    let props = fields.iter().map(|field| {
+        let ty = &field.ty;
+        let name = format!("{}", field.ident.as_ref().expect("should be field 
name"));
+        quote! {
+            (#name, <#ty as fury_core::serializer::Serializer>::ty())
+        }
+    });
+
+    quote! {
+        fn fury_hash() -> u32 {
+            use std::sync::Once;
+            static mut name_hash: u32 = 0u32;
+            static name_hash_once: Once = Once::new();
+            unsafe {
+                name_hash_once.call_once(|| {
+                        name_hash = 
fury_core::types::compute_struct_hash(vec![#(#props),*]);
+                });
+                name_hash
+            }
+        }
+    }
+}
+
+fn type_def(fields: &[&Field]) -> TokenStream {
+    let field_infos = fields.iter().map(|field| {
+        let ty = &field.ty;
+        let name = format!("{}", field.ident.as_ref().expect("should be field 
name"));
+        quote! {
+            fury_core::meta::FieldInfo::new(#name, <#ty as 
fury_core::serializer::Serializer>::ty())
+        }
+    });
+    quote! {
+        fn fury_type_def() -> &'static [u8] {
+            use std::sync::Once;
+            static mut type_definition: Vec<u8> = Vec::new();
+            static type_definition_once: Once = Once::new();
+            unsafe {
+                type_definition_once.call_once(|| {
+                    type_definition = fury_core::meta::TypeMeta::from_fields(
+                        0,
+                        vec![#(#field_infos),*]
+                    ).to_bytes().unwrap();
+                });
+                type_definition.as_slice()
+            }
+        }
+    }
+}
+
+pub fn gen_in_struct_impl(fields: &[&Field], tag: &String) -> TokenStream {
+    let hash_token_stream = hash(fields);
+    let type_def_token_stream = type_def(fields);
+
+    quote! {
+        #hash_token_stream
+
+        #type_def_token_stream
+
+        fn fury_tag() -> &'static str {
+            #tag
+        }
+    }
+}
+
+pub fn gen() -> TokenStream {
+    quote! {
+            fn ty() -> fury_core::types::FieldType {
+                fury_core::types::FieldType::FuryTypeTag
+            }
+    }
+}
diff --git a/rust/fury-core/src/internal/mod.rs 
b/rust/fury-derive/src/object/mod.rs
similarity index 88%
copy from rust/fury-core/src/internal/mod.rs
copy to rust/fury-derive/src/object/mod.rs
index 4b4db5d5..dae10f3a 100644
--- a/rust/fury-core/src/internal/mod.rs
+++ b/rust/fury-derive/src/object/mod.rs
@@ -15,12 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-mod bool;
-mod datetime;
-mod list;
-mod map;
-mod number;
-mod option;
-mod primitive_list;
-mod set;
-mod string;
+mod misc;
+mod read;
+mod serializer;
+mod write;
+
+pub use serializer::derive_serializer;
diff --git a/rust/fury-derive/src/object/read.rs 
b/rust/fury-derive/src/object/read.rs
new file mode 100644
index 00000000..de7176af
--- /dev/null
+++ b/rust/fury-derive/src/object/read.rs
@@ -0,0 +1,108 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use proc_macro2::{Ident, TokenStream};
+use quote::quote;
+use syn::Field;
+
+fn read(name: &Ident, fields: &[&Field]) -> TokenStream {
+    let assign_stmt = fields.iter().map(|field| {
+        let ty = &field.ty;
+        let ident = &field.ident;
+        quote! {
+            #ident: <#ty as 
fury_core::serializer::Serializer>::deserialize(context)?
+        }
+    });
+    quote! {
+        fn read(context: &mut fury_core::resolver::context::ReadContext) -> 
Result<Self, fury_core::error::Error> {
+            // read tag string
+            context.read_tag()?;
+            // read tag hash
+            let hash = context.reader.u32();
+            let expected = #name::fury_hash();
+            if(hash != expected) {
+                Err(fury_core::error::Error::StructHash{ expected, actial: 
hash })
+            } else {
+                Ok(Self {
+                    #(#assign_stmt),*
+                })
+            }
+        }
+    }
+}
+
+fn deserialize_compatible(name: &Ident, fields: &[&Field]) -> TokenStream {
+    let pattern_item = fields.iter().enumerate().map(|(index, field)| {
+        let ty = &field.ty;
+        let name = &field.ident;
+        quote! {
+            #index => {
+                result.#name = <#ty as 
fury_core::serializer::Serializer>::deserialize(context)?
+            }
+        }
+    });
+    quote! {
+        let ref_flag = context.reader.i8();
+        if ref_flag == (fury_core::types::RefFlag::NotNullValue as i8) || 
ref_flag == (fury_core::types::RefFlag::RefValue as i8) {
+            let mut result = Self::default();
+            let meta_index = context.reader.i16() as usize;
+            let meta = context.get_meta(meta_index).clone();
+            let fields = meta.get_field_info();
+            // read tag string
+            context.read_tag()?;
+            // read tag hash
+            let hash = context.reader.u32();
+            let expected = #name::fury_hash();
+            if(hash != expected) {
+                return Err(fury_core::error::Error::StructHash{ expected, 
actial: hash })
+            }
+            for (idx, _field_info) in fields.iter().enumerate() {
+                match idx {
+                    #(#pattern_item),*
+                    _ => {
+                        panic!("not implement yet")
+                    }
+                }
+            }
+            Ok(result)
+        } else if ref_flag == (fury_core::types::RefFlag::Null as i8) {
+            Err(fury_core::error::Error::Null)
+        } else if ref_flag == (fury_core::types::RefFlag::Ref as i8) {
+            Err(fury_core::error::Error::Ref)
+        } else {
+            Err(fury_core::error::Error::BadRefFlag)
+        }
+    }
+}
+
+pub fn gen(name: &Ident, fields: &[&Field]) -> TokenStream {
+    let read_token_stream = read(name, fields);
+    let compatible_token_stream = deserialize_compatible(name, fields);
+    quote! {
+        fn deserialize(context: &mut 
fury_core::resolver::context::ReadContext) -> Result<Self, 
fury_core::error::Error> {
+            match context.get_fury().get_mode() {
+                fury_core::types::Mode::SchemaConsistent => {
+                    fury_core::serializer::deserialize::<Self>(context)
+                },
+                fury_core::types::Mode::Compatible => {
+                    #compatible_token_stream
+                }
+            }
+        }
+        #read_token_stream
+    }
+}
diff --git a/rust/fury-derive/src/object/serializer.rs 
b/rust/fury-derive/src/object/serializer.rs
new file mode 100644
index 00000000..c8cbd721
--- /dev/null
+++ b/rust/fury-derive/src/object/serializer.rs
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::object::{misc, read, write};
+use crate::util::sorted_fields;
+use proc_macro::TokenStream;
+use quote::quote;
+
+pub fn derive_serializer(ast: &syn::DeriveInput, tag: &String) -> TokenStream {
+    let name = &ast.ident;
+    let fields = match &ast.data {
+        syn::Data::Struct(s) => sorted_fields(&s.fields),
+        _ => {
+            panic!("only struct be supported")
+        }
+    };
+
+    let misc_token_stream = misc::gen();
+    let struct_impl_token_stream = misc::gen_in_struct_impl(&fields, tag);
+    let write_token_stream = write::gen(name, &fields);
+    let read_token_stream = read::gen(name, &fields);
+
+    let gen = quote! {
+        impl #name {
+            #struct_impl_token_stream
+        }
+        impl fury_core::types::FuryGeneralList for #name {}
+        impl fury_core::serializer::Serializer for #name {
+            #misc_token_stream
+            #write_token_stream
+            #read_token_stream
+        }
+    };
+    gen.into()
+}
diff --git a/rust/fury-derive/src/object/write.rs 
b/rust/fury-derive/src/object/write.rs
new file mode 100644
index 00000000..83236be7
--- /dev/null
+++ b/rust/fury-derive/src/object/write.rs
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use proc_macro2::{Ident, TokenStream};
+use quote::quote;
+use syn::Field;
+
+pub fn gen(name: &Ident, fields: &[&Field]) -> TokenStream {
+    let accessor_expr = fields.iter().map(|field| {
+        let ty = &field.ty;
+        let ident = &field.ident;
+        quote! {
+            <#ty as 
fury_core::serializer::Serializer>::serialize(&self.#ident, context);
+        }
+    });
+
+    let reserved_size_expr = fields.iter().map(|field| {
+        let ty = &field.ty;
+        // each field have one byte ref tag and two byte type id
+        quote! {
+            <#ty as fury_core::serializer::Serializer>::reserved_space() + 
fury_core::types::SIZE_OF_REF_AND_TYPE
+        }
+    });
+
+    let tag_byte_len = format!("{}", name).len();
+
+    quote! {
+        fn serialize(&self, context: &mut 
fury_core::resolver::context::WriteContext) {
+            match context.get_fury().get_mode() {
+                fury_core::types::Mode::SchemaConsistent => {
+                    fury_core::serializer::serialize(self, context);
+                },
+                fury_core::types::Mode::Compatible => {
+                    context.writer.i8(fury_core::types::RefFlag::NotNullValue 
as i8);
+                    let meta_index = context.push_meta(
+                            std::any::TypeId::of::<Self>(),
+                            #name::fury_type_def()
+                        ) as i16;
+                    context.writer.i16(meta_index);
+                    self.write(context);
+                }
+            }
+        }
+
+
+        fn write(&self, context: &mut 
fury_core::resolver::context::WriteContext) {
+            // write tag string
+            context.write_tag(#name::fury_tag());
+            // write tag hash
+            context.writer.u32(#name::fury_hash());
+            // write fields
+            #(#accessor_expr)*
+        }
+
+        fn reserved_space() -> usize {
+            // struct have four byte hash
+            #tag_byte_len + 4 + #(#reserved_size_expr)+*
+        }
+    }
+}
diff --git a/rust/fury-core/src/internal/mod.rs b/rust/fury-derive/src/util.rs
similarity index 79%
rename from rust/fury-core/src/internal/mod.rs
rename to rust/fury-derive/src/util.rs
index 4b4db5d5..0c4d622c 100644
--- a/rust/fury-core/src/internal/mod.rs
+++ b/rust/fury-derive/src/util.rs
@@ -15,12 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-mod bool;
-mod datetime;
-mod list;
-mod map;
-mod number;
-mod option;
-mod primitive_list;
-mod set;
-mod string;
+use syn::{Field, Fields};
+
+pub fn sorted_fields(fields: &Fields) -> Vec<&Field> {
+    let mut fields = fields.iter().collect::<Vec<&Field>>();
+    fields.sort_by(|a, b| a.ident.cmp(&b.ident));
+    fields
+}
diff --git a/rust/tests/Cargo.toml b/rust/tests/Cargo.toml
index 07a8afa7..fdb64196 100644
--- a/rust/tests/Cargo.toml
+++ b/rust/tests/Cargo.toml
@@ -27,4 +27,3 @@ fury-core = { path = "../fury-core" }
 fury-derive = { path = "../fury-derive" }
 
 chrono = "0.4"
-lazy_static = { version = "1.4" }
diff --git a/rust/tests/tests/test_complex_struct.rs 
b/rust/tests/tests/test_complex_struct.rs
index fddf5eb5..4eea7a9e 100644
--- a/rust/tests/tests/test_complex_struct.rs
+++ b/rust/tests/tests/test_complex_struct.rs
@@ -17,18 +17,19 @@
 
 use chrono::{DateTime, NaiveDate, NaiveDateTime};
 use fury_core::fury::Fury;
+use fury_core::types::Mode;
 use fury_derive::Fury;
 use std::collections::HashMap;
 
 #[test]
 fn complex_struct() {
-    #[derive(Fury, Debug, PartialEq)]
+    #[derive(Fury, Debug, PartialEq, Default)]
     #[tag("example.foo2")]
     struct Animal {
         category: String,
     }
 
-    #[derive(Fury, Debug, PartialEq)]
+    #[derive(Fury, Debug, PartialEq, Default)]
     #[tag("example.foo")]
     struct Person {
         c1: Vec<u8>,  // binary
@@ -65,7 +66,7 @@ fn complex_struct() {
         c5: 2.0,
         c6: 4.0,
     };
-    let fury = Fury::default();
+    let fury = Fury::default().mode(Mode::Compatible);
     let bin: Vec<u8> = fury.serialize(&person);
     let obj: Person = fury.deserialize(&bin).expect("should success");
     assert_eq!(person, obj);
@@ -73,13 +74,13 @@ fn complex_struct() {
 
 #[test]
 fn encode_to_obin() {
-    #[derive(Fury, Debug, PartialEq)]
+    #[derive(Fury, Debug, PartialEq, Default)]
     #[tag("example.foo2")]
     struct Animal {
         category: String,
     }
 
-    #[derive(Fury, Debug, PartialEq)]
+    #[derive(Fury, Debug, PartialEq, Default)]
     #[tag("example.ComplexObject")]
     struct Person {
         f1: String,


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to