This is an automated email from the ASF dual-hosted git repository.
pandalee pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new a0c107b2f chore(rust): reorder fory rust methods (#2813)
a0c107b2f is described below
commit a0c107b2f4802e2658f820136a05a6bf013a7d9b
Author: Shawn Yang <[email protected]>
AuthorDate: Thu Oct 23 12:29:28 2025 +0800
chore(rust): reorder fory rust methods (#2813)
## Why?
<!-- Describe the purpose of this PR. -->
## What does this PR do?
reorder fory rust methods:
1. getter/setter first
2. register next
3. serialize
4. deserialize
## Related issues
<!--
Is there any related issue? If this PR closes them you say say
fix/closes:
- #xxxx0
- #xxxx1
- Fixes #xxxx2
-->
## Does this PR introduce any user-facing change?
<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fory/issues/new/choose) describing the
need to do so and update the document if necessary.
Delete section if not applicable.
-->
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
<!--
When the PR has an impact on performance (if you don't know whether the
PR will have an impact on performance, you can submit the PR first, and
if it will have impact on performance, the code reviewer will explain
it), be sure to attach a benchmark data here.
Delete section if not applicable.
-->
---
rust/fory-core/src/fory.rs | 468 ++++++++++++------------
rust/fory-core/src/lib.rs | 2 +-
rust/fory-core/src/serializer/core.rs | 18 +
rust/fory-core/src/serializer/mod.rs | 2 +-
rust/fory-core/src/serializer/util.rs | 2 +-
rust/tests/tests/compatible/test_struct_enum.rs | 2 +-
rust/tests/tests/test_cross_language.rs | 2 +-
rust/tests/tests/test_ext.rs | 2 +-
8 files changed, 254 insertions(+), 244 deletions(-)
diff --git a/rust/fory-core/src/fory.rs b/rust/fory-core/src/fory.rs
index 53c5f7b4f..db55d1cea 100644
--- a/rust/fory-core/src/fory.rs
+++ b/rust/fory-core/src/fory.rs
@@ -339,238 +339,6 @@ impl Fory {
&self.type_resolver
}
- pub fn write_head<T: Serializer>(&self, is_none: bool, writer: &mut
Writer) {
- const HEAD_SIZE: usize = 10;
- writer.reserve(T::fory_reserved_space() + SIZE_OF_REF_AND_TYPE +
HEAD_SIZE);
- if self.xlang {
- writer.write_u16(MAGIC_NUMBER);
- }
- #[cfg(target_endian = "big")]
- let mut bitmap = 0;
- #[cfg(target_endian = "little")]
- let mut bitmap = IS_LITTLE_ENDIAN_FLAG;
- if self.xlang {
- bitmap |= IS_CROSS_LANGUAGE_FLAG;
- }
- if is_none {
- bitmap |= IS_NULL_FLAG;
- }
- writer.write_u8(bitmap);
- if is_none {
- return;
- }
- if self.xlang {
- writer.write_u8(Language::Rust as u8);
- }
- }
-
- #[inline(always)]
- fn read_head(&self, reader: &mut Reader) -> Result<bool, Error> {
- if self.xlang {
- let magic_numer = reader.read_u16()?;
- ensure!(
- magic_numer == MAGIC_NUMBER,
- Error::invalid_data(format!(
- "The fory xlang serialization must start with magic number
{:X}. \
- Please check whether the serialization is based on the
xlang protocol \
- and the data didn't corrupt.",
- MAGIC_NUMBER
- ))
- )
- }
- let bitmap = reader.read_u8()?;
- let peer_is_xlang = (bitmap & IS_CROSS_LANGUAGE_FLAG) != 0;
- ensure!(
- self.xlang == peer_is_xlang,
- Error::invalid_data("header bitmap mismatch at xlang bit")
- );
- let is_little_endian = (bitmap & IS_LITTLE_ENDIAN_FLAG) != 0;
- ensure!(
- is_little_endian,
- Error::invalid_data(
- "Big endian is not supported for now, please ensure peer
machine is little endian."
- )
- );
- let is_none = (bitmap & IS_NULL_FLAG) != 0;
- if is_none {
- return Ok(true);
- }
- if peer_is_xlang {
- let _peer_lang = reader.read_u8()?;
- }
- Ok(false)
- }
-
- /// Deserializes data from a byte slice into a value of type `T`.
- ///
- /// # Type Parameters
- ///
- /// * `T` - The target type to deserialize into. Must implement
`Serializer` and `ForyDefault`.
- ///
- /// # Arguments
- ///
- /// * `bf` - The byte slice containing the serialized data.
- ///
- /// # Returns
- ///
- /// * `Ok(T)` - The deserialized value on success.
- /// * `Err(Error)` - An error if deserialization fails (e.g., invalid
format, type mismatch).
- ///
- /// # Panics
- ///
- /// Panics in debug mode if there are unread bytes remaining after
successful deserialization,
- /// indicating a potential protocol violation.
- ///
- /// # Examples
- ///
- /// ```rust, ignore
- /// use fory::Fory;
- /// use fory::ForyObject;
- ///
- /// #[derive(ForyObject)]
- /// struct Point { x: i32, y: i32 }
- ///
- /// let fory = Fory::default();
- /// let point = Point { x: 10, y: 20 };
- /// let bytes = fory.serialize(&point);
- /// let deserialized: Point = fory.deserialize(&bytes).unwrap();
- /// ```
- pub fn deserialize<T: Serializer + ForyDefault>(&self, bf: &[u8]) ->
Result<T, Error> {
- let pool = self.read_context_pool.get_or_init(|| {
- let type_resolver = self.type_resolver.clone();
- let compatible = self.compatible;
- let share_meta = self.share_meta;
- let xlang = self.xlang;
- let max_dyn_depth = self.max_dyn_depth;
- let check_struct_version = self.check_struct_version;
-
- let factory = move || {
- let reader = Reader::new(&[]);
- Box::new(ReadContext::new(
- reader,
- type_resolver.clone(),
- compatible,
- share_meta,
- xlang,
- max_dyn_depth,
- check_struct_version,
- ))
- };
- Pool::new(factory)
- });
- let mut context = pool.get();
- context.init(bf, self.max_dyn_depth);
- let result = self.deserialize_with_context(&mut context);
- if result.is_ok() {
- assert_eq!(context.reader.slice_after_cursor().len(), 0);
- }
- context.reader.reset();
- pool.put(context);
- result
- }
-
- pub fn deserialize_with_context<T: Serializer + ForyDefault>(
- &self,
- context: &mut ReadContext,
- ) -> Result<T, Error> {
- let is_none = self.read_head(&mut context.reader)?;
- if is_none {
- return Ok(T::fory_default());
- }
- let mut bytes_to_skip = 0;
- if context.is_compatible() {
- let meta_offset = context.reader.read_i32()?;
- if meta_offset != -1 {
- bytes_to_skip = context.load_type_meta(meta_offset as usize)?;
- }
- }
- let result = <T as Serializer>::fory_read(context, true, true);
- if bytes_to_skip > 0 {
- context.reader.skip(bytes_to_skip)?;
- }
- context.ref_reader.resolve_callbacks();
- context.reset();
- result
- }
-
- /// Serializes a value of type `T` into a byte vector.
- ///
- /// # Type Parameters
- ///
- /// * `T` - The type of the value to serialize. Must implement
`Serializer`.
- ///
- /// # Arguments
- ///
- /// * `record` - A reference to the value to serialize.
- ///
- /// # Returns
- ///
- /// A `Vec<u8>` containing the serialized data.
- ///
- /// # Examples
- ///
- /// ```rust, ignore
- /// use fory::Fory;
- /// use fory::ForyObject;
- ///
- /// #[derive(ForyObject)]
- /// struct Point { x: i32, y: i32 }
- ///
- /// let fory = Fory::default();
- /// let point = Point { x: 10, y: 20 };
- /// let bytes = fory.serialize(&point);
- /// ```
- pub fn serialize<T: Serializer>(&self, record: &T) -> Result<Vec<u8>,
Error> {
- let pool = self.write_context_pool.get_or_init(|| {
- let type_resolver = self.type_resolver.clone();
- let compatible = self.compatible;
- let share_meta = self.share_meta;
- let compress_string = self.compress_string;
- let xlang = self.xlang;
- let check_struct_version = self.check_struct_version;
-
- let factory = move || {
- let writer = Writer::default();
- Box::new(WriteContext::new(
- writer,
- type_resolver.clone(),
- compatible,
- share_meta,
- compress_string,
- xlang,
- check_struct_version,
- ))
- };
- Pool::new(factory)
- });
- let mut context = pool.get();
- let result = self.serialize_with_context(record, &mut context)?;
- pool.put(context);
- Ok(result)
- }
-
- pub fn serialize_with_context<T: Serializer>(
- &self,
- record: &T,
- context: &mut WriteContext,
- ) -> Result<Vec<u8>, Error> {
- context.writer.attach_buffer(vec![]);
- let is_none = record.fory_is_none();
- self.write_head::<T>(is_none, &mut context.writer);
- let meta_start_offset = context.writer.len();
- if !is_none {
- if context.is_compatible() {
- context.writer.write_i32(-1);
- };
- <T as Serializer>::fory_write(record, context, true, true, false)?;
- if context.is_compatible() && !context.empty() {
- context.write_meta(meta_start_offset);
- }
- }
- context.reset();
- Ok(context.writer.detach_buffer())
- }
-
/// Registers a struct type with a numeric type ID for serialization.
///
/// # Type Parameters
@@ -764,12 +532,236 @@ impl Fory {
) -> Result<(), Error> {
self.type_resolver.register_generic_trait::<T>()
}
-}
-pub fn write_data<T: Serializer>(this: &T, context: &mut WriteContext) ->
Result<(), Error> {
- T::fory_write_data(this, context)
-}
+ /// Serializes a value of type `T` into a byte vector.
+ ///
+ /// # Type Parameters
+ ///
+ /// * `T` - The type of the value to serialize. Must implement
`Serializer`.
+ ///
+ /// # Arguments
+ ///
+ /// * `record` - A reference to the value to serialize.
+ ///
+ /// # Returns
+ ///
+ /// A `Vec<u8>` containing the serialized data.
+ ///
+ /// # Examples
+ ///
+ /// ```rust, ignore
+ /// use fory::Fory;
+ /// use fory::ForyObject;
+ ///
+ /// #[derive(ForyObject)]
+ /// struct Point { x: i32, y: i32 }
+ ///
+ /// let fory = Fory::default();
+ /// let point = Point { x: 10, y: 20 };
+ /// let bytes = fory.serialize(&point);
+ /// ```
+ pub fn serialize<T: Serializer>(&self, record: &T) -> Result<Vec<u8>,
Error> {
+ let pool = self.write_context_pool.get_or_init(|| {
+ let type_resolver = self.type_resolver.clone();
+ let compatible = self.compatible;
+ let share_meta = self.share_meta;
+ let compress_string = self.compress_string;
+ let xlang = self.xlang;
+ let check_struct_version = self.check_struct_version;
+
+ let factory = move || {
+ let writer = Writer::default();
+ Box::new(WriteContext::new(
+ writer,
+ type_resolver.clone(),
+ compatible,
+ share_meta,
+ compress_string,
+ xlang,
+ check_struct_version,
+ ))
+ };
+ Pool::new(factory)
+ });
+ let mut context = pool.get();
+ let result = self.serialize_with_context(record, &mut context)?;
+ pool.put(context);
+ Ok(result)
+ }
+
+ pub fn serialize_with_context<T: Serializer>(
+ &self,
+ record: &T,
+ context: &mut WriteContext,
+ ) -> Result<Vec<u8>, Error> {
+ context.writer.attach_buffer(vec![]);
+ let is_none = record.fory_is_none();
+ self.write_head::<T>(is_none, &mut context.writer);
+ let meta_start_offset = context.writer.len();
+ if !is_none {
+ if context.is_compatible() {
+ context.writer.write_i32(-1);
+ };
+ <T as Serializer>::fory_write(record, context, true, true, false)?;
+ if context.is_compatible() && !context.empty() {
+ context.write_meta(meta_start_offset);
+ }
+ }
+ context.reset();
+ Ok(context.writer.detach_buffer())
+ }
+
+ pub fn write_head<T: Serializer>(&self, is_none: bool, writer: &mut
Writer) {
+ const HEAD_SIZE: usize = 10;
+ writer.reserve(T::fory_reserved_space() + SIZE_OF_REF_AND_TYPE +
HEAD_SIZE);
+ if self.xlang {
+ writer.write_u16(MAGIC_NUMBER);
+ }
+ #[cfg(target_endian = "big")]
+ let mut bitmap = 0;
+ #[cfg(target_endian = "little")]
+ let mut bitmap = IS_LITTLE_ENDIAN_FLAG;
+ if self.xlang {
+ bitmap |= IS_CROSS_LANGUAGE_FLAG;
+ }
+ if is_none {
+ bitmap |= IS_NULL_FLAG;
+ }
+ writer.write_u8(bitmap);
+ if is_none {
+ return;
+ }
+ if self.xlang {
+ writer.write_u8(Language::Rust as u8);
+ }
+ }
+
+ /// Deserializes data from a byte slice into a value of type `T`.
+ ///
+ /// # Type Parameters
+ ///
+ /// * `T` - The target type to deserialize into. Must implement
`Serializer` and `ForyDefault`.
+ ///
+ /// # Arguments
+ ///
+ /// * `bf` - The byte slice containing the serialized data.
+ ///
+ /// # Returns
+ ///
+ /// * `Ok(T)` - The deserialized value on success.
+ /// * `Err(Error)` - An error if deserialization fails (e.g., invalid
format, type mismatch).
+ ///
+ /// # Panics
+ ///
+ /// Panics in debug mode if there are unread bytes remaining after
successful deserialization,
+ /// indicating a potential protocol violation.
+ ///
+ /// # Examples
+ ///
+ /// ```rust, ignore
+ /// use fory::Fory;
+ /// use fory::ForyObject;
+ ///
+ /// #[derive(ForyObject)]
+ /// struct Point { x: i32, y: i32 }
+ ///
+ /// let fory = Fory::default();
+ /// let point = Point { x: 10, y: 20 };
+ /// let bytes = fory.serialize(&point);
+ /// let deserialized: Point = fory.deserialize(&bytes).unwrap();
+ /// ```
+ pub fn deserialize<T: Serializer + ForyDefault>(&self, bf: &[u8]) ->
Result<T, Error> {
+ let pool = self.read_context_pool.get_or_init(|| {
+ let type_resolver = self.type_resolver.clone();
+ let compatible = self.compatible;
+ let share_meta = self.share_meta;
+ let xlang = self.xlang;
+ let max_dyn_depth = self.max_dyn_depth;
+ let check_struct_version = self.check_struct_version;
+
+ let factory = move || {
+ let reader = Reader::new(&[]);
+ Box::new(ReadContext::new(
+ reader,
+ type_resolver.clone(),
+ compatible,
+ share_meta,
+ xlang,
+ max_dyn_depth,
+ check_struct_version,
+ ))
+ };
+ Pool::new(factory)
+ });
+ let mut context = pool.get();
+ context.init(bf, self.max_dyn_depth);
+ let result = self.deserialize_with_context(&mut context);
+ if result.is_ok() {
+ assert_eq!(context.reader.slice_after_cursor().len(), 0);
+ }
+ context.reader.reset();
+ pool.put(context);
+ result
+ }
+
+ pub fn deserialize_with_context<T: Serializer + ForyDefault>(
+ &self,
+ context: &mut ReadContext,
+ ) -> Result<T, Error> {
+ let is_none = self.read_head(&mut context.reader)?;
+ if is_none {
+ return Ok(T::fory_default());
+ }
+ let mut bytes_to_skip = 0;
+ if context.is_compatible() {
+ let meta_offset = context.reader.read_i32()?;
+ if meta_offset != -1 {
+ bytes_to_skip = context.load_type_meta(meta_offset as usize)?;
+ }
+ }
+ let result = <T as Serializer>::fory_read(context, true, true);
+ if bytes_to_skip > 0 {
+ context.reader.skip(bytes_to_skip)?;
+ }
+ context.ref_reader.resolve_callbacks();
+ context.reset();
+ result
+ }
-pub fn read_data<T: Serializer + ForyDefault>(context: &mut ReadContext) ->
Result<T, Error> {
- T::fory_read_data(context)
+ #[inline(always)]
+ fn read_head(&self, reader: &mut Reader) -> Result<bool, Error> {
+ if self.xlang {
+ let magic_numer = reader.read_u16()?;
+ ensure!(
+ magic_numer == MAGIC_NUMBER,
+ Error::invalid_data(format!(
+ "The fory xlang serialization must start with magic number
{:X}. \
+ Please check whether the serialization is based on the
xlang protocol \
+ and the data didn't corrupt.",
+ MAGIC_NUMBER
+ ))
+ )
+ }
+ let bitmap = reader.read_u8()?;
+ let peer_is_xlang = (bitmap & IS_CROSS_LANGUAGE_FLAG) != 0;
+ ensure!(
+ self.xlang == peer_is_xlang,
+ Error::invalid_data("header bitmap mismatch at xlang bit")
+ );
+ let is_little_endian = (bitmap & IS_LITTLE_ENDIAN_FLAG) != 0;
+ ensure!(
+ is_little_endian,
+ Error::invalid_data(
+ "Big endian is not supported for now, please ensure peer
machine is little endian."
+ )
+ );
+ let is_none = (bitmap & IS_NULL_FLAG) != 0;
+ if is_none {
+ return Ok(true);
+ }
+ if peer_is_xlang {
+ let _peer_lang = reader.read_u8()?;
+ }
+ Ok(false)
+ }
}
diff --git a/rust/fory-core/src/lib.rs b/rust/fory-core/src/lib.rs
index cbb277898..c58559b88 100644
--- a/rust/fory-core/src/lib.rs
+++ b/rust/fory-core/src/lib.rs
@@ -195,5 +195,5 @@ pub use crate::fory::Fory;
pub use crate::resolver::context::{ReadContext, WriteContext};
pub use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
pub use crate::serializer::weak::{ArcWeak, RcWeak};
-pub use crate::serializer::{ForyDefault, Serializer, StructSerializer};
+pub use crate::serializer::{read_data, write_data, ForyDefault, Serializer,
StructSerializer};
pub use crate::types::{RefFlag, TypeId};
diff --git a/rust/fory-core/src/serializer/core.rs
b/rust/fory-core/src/serializer/core.rs
index 72e329afb..a8888ada8 100644
--- a/rust/fory-core/src/serializer/core.rs
+++ b/rust/fory-core/src/serializer/core.rs
@@ -1432,3 +1432,21 @@ pub trait StructSerializer: Serializer + 'static {
where
Self: Sized;
}
+
+/// Serializes an object implementing `Serializer` to the write context.
+///
+/// This is a convenience wrapper around `T::fory_write_data` that delegates
to the type's
+/// serialization implementation.
+#[inline(always)]
+pub fn write_data<T: Serializer>(this: &T, context: &mut WriteContext) ->
Result<(), Error> {
+ T::fory_write_data(this, context)
+}
+
+/// Deserializes an object implementing `Serializer` from the read context.
+///
+/// This is a convenience wrapper around `T::fory_read_data` that delegates to
the type's
+/// deserialization implementation. Requires `ForyDefault` for instance
creation.
+#[inline(always)]
+pub fn read_data<T: Serializer + ForyDefault>(context: &mut ReadContext) ->
Result<T, Error> {
+ T::fory_read_data(context)
+}
diff --git a/rust/fory-core/src/serializer/mod.rs
b/rust/fory-core/src/serializer/mod.rs
index db2739089..b173355a4 100644
--- a/rust/fory-core/src/serializer/mod.rs
+++ b/rust/fory-core/src/serializer/mod.rs
@@ -41,4 +41,4 @@ pub mod weak;
mod core;
pub use any::{read_box_any, write_box_any};
-pub use core::{ForyDefault, Serializer, StructSerializer};
+pub use core::{read_data, write_data, ForyDefault, Serializer,
StructSerializer};
diff --git a/rust/fory-core/src/serializer/util.rs
b/rust/fory-core/src/serializer/util.rs
index a344ce002..a4adca7b4 100644
--- a/rust/fory-core/src/serializer/util.rs
+++ b/rust/fory-core/src/serializer/util.rs
@@ -18,7 +18,7 @@
use crate::ensure;
use crate::error::Error;
use crate::resolver::context::{ReadContext, WriteContext};
-use crate::serializer::{bool, Serializer};
+use crate::serializer::Serializer;
use crate::types::TypeId;
const NO_REF_FLAG_TYPE_IDS: [u32; 7] = [
diff --git a/rust/tests/tests/compatible/test_struct_enum.rs
b/rust/tests/tests/compatible/test_struct_enum.rs
index 9919ecc32..86bcda78f 100644
--- a/rust/tests/tests/compatible/test_struct_enum.rs
+++ b/rust/tests/tests/compatible/test_struct_enum.rs
@@ -18,10 +18,10 @@
use chrono::{NaiveDate, NaiveDateTime};
use fory_core::buffer::{Reader, Writer};
use fory_core::error::Error;
-use fory_core::fory::{read_data, write_data, Fory};
use fory_core::resolver::context::{ReadContext, WriteContext};
use fory_core::serializer::{ForyDefault, Serializer};
use fory_core::TypeResolver;
+use fory_core::{read_data, write_data, Fory};
use fory_derive::ForyObject;
use std::collections::{HashMap, HashSet};
diff --git a/rust/tests/tests/test_cross_language.rs
b/rust/tests/tests/test_cross_language.rs
index a1d716faa..7415bfde1 100644
--- a/rust/tests/tests/test_cross_language.rs
+++ b/rust/tests/tests/test_cross_language.rs
@@ -18,11 +18,11 @@
use chrono::{NaiveDate, NaiveDateTime};
use fory_core::buffer::{Reader, Writer};
use fory_core::error::Error;
-use fory_core::fory::{read_data, write_data, Fory};
use fory_core::meta::murmurhash3_x64_128;
use fory_core::resolver::context::{ReadContext, WriteContext};
use fory_core::serializer::{ForyDefault, Serializer};
use fory_core::TypeResolver;
+use fory_core::{read_data, write_data, Fory};
use fory_derive::ForyObject;
use std::collections::{HashMap, HashSet};
use std::{fs, vec};
diff --git a/rust/tests/tests/test_ext.rs b/rust/tests/tests/test_ext.rs
index 625bc4386..f93f80a60 100644
--- a/rust/tests/tests/test_ext.rs
+++ b/rust/tests/tests/test_ext.rs
@@ -46,7 +46,7 @@ fn test_duplicate_impl() {
#[test]
fn test_use() {
- use fory_core::fory::{read_data, write_data};
+ use fory_core::{read_data, write_data};
#[derive(Debug, PartialEq)]
struct Item {
f1: i32,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]