Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions rust/fory-core/src/fory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,42 @@ impl Fory {
result
}

pub fn deserialize_into<T: Serializer + ForyDefault>(
&self,
bf: &[u8],
output: &mut T,
) -> Result<(), 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 factory = move || {
let reader = Reader::new(&[]);
ReadContext::new(
reader,
type_resolver.clone(),
compatible,
share_meta,
xlang,
max_dyn_depth,
)
};
Pool::new(factory)
});
let mut context = pool.get();
context.init(bf, self.max_dyn_depth);
let result = self.deserialize_into_with_context(&mut context, output);
if result.is_ok() {
assert_eq!(context.reader.slice_after_cursor().len(), 0);
}
context.reset();
pool.put(context);
result
}

pub fn deserialize_with_context<T: Serializer + ForyDefault>(
&self,
context: &mut ReadContext,
Expand All @@ -437,6 +473,30 @@ impl Fory {
result
}

pub fn deserialize_into_with_context<T: Serializer + ForyDefault>(
&self,
context: &mut ReadContext,
output: &mut T,
) -> Result<(), Error> {
let is_none = self.read_head(&mut context.reader)?;
if is_none {
return Ok(());
}
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_meta(meta_offset as usize)?;
}
}
<T as Serializer>::fory_read_into(context, false, output)?;
if bytes_to_skip > 0 {
context.reader.skip(bytes_to_skip)?;
}
context.ref_reader.resolve_callbacks();
Ok(())
}

/// Serializes a value of type `T` into a byte vector.
///
/// # Type Parameters
Expand Down
124 changes: 124 additions & 0 deletions rust/fory-core/src/serializer/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,30 @@ impl Serializer for Box<dyn Any> {
deserialize_any_box(context)
}

fn fory_read_into(
context: &mut ReadContext,
_is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
let new_value = deserialize_any_box(context)?;
*output = new_value;
Ok(())
}

fn fory_read_data(context: &mut ReadContext, _is_field: bool) -> Result<Self, Error> {
deserialize_any_box(context)
}

fn fory_read_data_into(
context: &mut ReadContext,
_is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
let new_value = deserialize_any_box(context)?;
*output = new_value;
Ok(())
}

fn fory_get_type_id(_: &TypeResolver) -> Result<u32, Error> {
unreachable!("Box<dyn Any> has no static type ID - use fory_type_id_dyn")
}
Expand Down Expand Up @@ -168,10 +188,62 @@ impl Serializer for Rc<dyn Any> {
}
}

fn fory_read_into(
context: &mut ReadContext,
_is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;

match ref_flag {
RefFlag::Null => Err(Error::InvalidRef("Rc<dyn Any> cannot be null".into())),
RefFlag::Ref => {
let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
*output = context
.ref_reader
.get_rc_ref::<dyn Any>(ref_id)
.ok_or_else(|| {
Error::InvalidData(
format!("Rc<dyn Any> reference {} not found", ref_id).into(),
)
})?;
Ok(())
}
RefFlag::NotNullValue => {
context.inc_depth()?;
let harness = context.read_any_typeinfo()?;
let deserializer_fn = harness.get_read_data_fn();
let boxed = deserializer_fn(context, true)?;
context.dec_depth();
*output = Rc::<dyn Any>::from(boxed);
Ok(())
}
RefFlag::RefValue => {
context.inc_depth()?;
let harness = context.read_any_typeinfo()?;
let deserializer_fn = harness.get_read_data_fn();
let boxed = deserializer_fn(context, true)?;
context.dec_depth();
let rc: Rc<dyn Any> = Rc::from(boxed);
context.ref_reader.store_rc_ref(rc.clone());
*output = rc;
Ok(())
}
}
}

fn fory_read_data(context: &mut ReadContext, is_field: bool) -> Result<Self, Error> {
Self::fory_read(context, is_field)
}

fn fory_read_data_into(
context: &mut ReadContext,
_is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
Self::fory_read_into(context, _is_field, output)
}

fn fory_get_type_id(_: &TypeResolver) -> Result<u32, Error> {
unreachable!("Rc<dyn Any> has no static type ID - use fory_type_id_dyn")
}
Expand Down Expand Up @@ -263,10 +335,62 @@ impl Serializer for Arc<dyn Any> {
}
}

fn fory_read_into(
context: &mut ReadContext,
_is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;

match ref_flag {
RefFlag::Null => Err(Error::InvalidRef("Arc<dyn Any> cannot be null".into())),
RefFlag::Ref => {
let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
*output = context
.ref_reader
.get_arc_ref::<dyn Any>(ref_id)
.ok_or_else(|| {
Error::InvalidData(
format!("Arc<dyn Any> reference {} not found", ref_id).into(),
)
})?;
Ok(())
}
RefFlag::NotNullValue => {
context.inc_depth()?;
let harness = context.read_any_typeinfo()?;
let deserializer_fn = harness.get_read_data_fn();
let boxed = deserializer_fn(context, true)?;
context.dec_depth();
*output = Arc::<dyn Any>::from(boxed);
Ok(())
}
RefFlag::RefValue => {
context.inc_depth()?;
let harness = context.read_any_typeinfo()?;
let deserializer_fn = harness.get_read_data_fn();
let boxed = deserializer_fn(context, true)?;
context.dec_depth();
let arc: Arc<dyn Any> = Arc::from(boxed);
context.ref_reader.store_arc_ref(arc.clone());
*output = arc;
Ok(())
}
}
}

fn fory_read_data(context: &mut ReadContext, is_field: bool) -> Result<Self, Error> {
Self::fory_read(context, is_field)
}

fn fory_read_data_into(
context: &mut ReadContext,
_is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
Self::fory_read_into(context, _is_field, output)
}

fn fory_get_type_id(_type_resolver: &TypeResolver) -> Result<u32, Error> {
unreachable!("Arc<dyn Any> has no static type ID - use fory_type_id_dyn")
}
Expand Down
44 changes: 44 additions & 0 deletions rust/fory-core/src/serializer/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,56 @@ impl<T: Serializer + ForyDefault + Send + Sync + 'static> Serializer for Arc<T>
})
}

fn fory_read_into(
context: &mut ReadContext,
is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;

match ref_flag {
RefFlag::Null => Err(Error::InvalidRef("Arc cannot be null".into()))?,
RefFlag::Ref => {
let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
*output = context
.ref_reader
.get_arc_ref::<T>(ref_id)
.ok_or(Error::InvalidData(
format!("Arc reference {ref_id} not found").into(),
))?;
Ok(())
}
RefFlag::NotNullValue => {
let mut inner = T::fory_default();
T::fory_read_data_into(context, is_field, &mut inner)?;
*output = Arc::new(inner);
Ok(())
}
RefFlag::RefValue => {
let ref_id = context.ref_reader.reserve_ref_id();
let mut inner = T::fory_default();
T::fory_read_data_into(context, is_field, &mut inner)?;
*output = Arc::new(inner);
context.ref_reader.store_arc_ref_at(ref_id, output.clone());
Ok(())
}
}
}

fn fory_read_data(context: &mut ReadContext, is_field: bool) -> Result<Self, Error> {
// When Arc is nested inside another shared ref, fory_read_data is called.
// Delegate to fory_read which handles ref tracking properly.
Self::fory_read(context, is_field)
}

fn fory_read_data_into(
context: &mut ReadContext,
is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
Self::fory_read_into(context, is_field, output)
}

fn fory_read_type_info(context: &mut ReadContext, is_field: bool) -> Result<(), Error> {
T::fory_read_type_info(context, is_field)
}
Expand Down
10 changes: 10 additions & 0 deletions rust/fory-core/src/serializer/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ impl Serializer for bool {
Ok(context.reader.read_u8()? == 1)
}

#[inline(always)]
fn fory_read_data_into(
context: &mut ReadContext,
_is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
*output = context.reader.read_u8()? == 1;
Ok(())
}

#[inline(always)]
fn fory_reserved_space() -> usize {
mem::size_of::<i32>()
Expand Down
9 changes: 9 additions & 0 deletions rust/fory-core/src/serializer/box_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ impl<T: Serializer + ForyDefault> Serializer for Box<T> {
Ok(Box::new(T::fory_read_data(context, is_field)?))
}

fn fory_read_data_into(
context: &mut ReadContext,
is_field: bool,
output: &mut Self,
) -> Result<(), Error> {
*output = Box::new(T::fory_read_data(context, is_field)?);
Ok(())
}

fn fory_read_type_info(context: &mut ReadContext, is_field: bool) -> Result<(), Error> {
T::fory_read_type_info(context, is_field)
}
Expand Down
40 changes: 40 additions & 0 deletions rust/fory-core/src/serializer/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,43 @@ where
.collect::<Result<C, Error>>()
}
}

pub fn read_collection_into<C, T>(context: &mut ReadContext, output: &mut C) -> Result<(), Error>
where
T: Serializer + ForyDefault,
C: FromIterator<T> + Default + Extend<T>,
{
let len = context.reader.read_varuint32()?;
*output = C::default();
if len == 0 {
return Ok(());
}
let header = context.reader.read_u8()?;
let declared = (header & DECL_ELEMENT_TYPE) != 0;
T::fory_read_type_info(context, declared)?;
let has_null = (header & HAS_NULL) != 0;
let is_same_type = (header & IS_SAME_TYPE) != 0;
if T::fory_is_polymorphic() || T::fory_is_shared_ref() {
(0..len).try_for_each(|_| {
let mut element = T::fory_default();
T::fory_read_into(context, declared, &mut element)?;
output.extend(std::iter::once(element));
Ok(())
})
} else {
let skip_ref_flag = is_same_type && !has_null;
// let skip_ref_flag = crate::serializer::get_skip_ref_flag::<T>(context.get_fory());
(0..len).try_for_each(|_| {
let mut element = T::fory_default();
crate::serializer::read_ref_info_data_into(
context,
declared,
skip_ref_flag,
true,
&mut element,
)?;
output.extend(std::iter::once(element));
Ok(())
})
}
}
Loading
Loading