use crate::error::Error;
use crate::resolver::context::{ReadContext, WriteContext};
use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
use crate::serializer::{ForyDefault, Serializer};
use crate::types::{RefFlag, RefMode, TypeId};
use std::rc::Rc;
use std::sync::Arc;
impl<T: Serializer + ForyDefault + Send + Sync + 'static> Serializer for Arc<T> {
fn fory_is_shared_ref() -> bool {
true
}
fn fory_write(
&self,
context: &mut WriteContext,
ref_mode: RefMode,
write_type_info: bool,
has_generics: bool,
) -> Result<(), Error> {
match ref_mode {
RefMode::None => {
if write_type_info {
T::fory_write_type_info(context)?;
}
T::fory_write_data_generic(self, context, has_generics)
}
RefMode::NullOnly => {
context.writer.write_i8(RefFlag::NotNullValue as i8);
if write_type_info {
T::fory_write_type_info(context)?;
}
T::fory_write_data_generic(self, context, has_generics)
}
RefMode::Tracking => {
if context
.ref_writer
.try_write_arc_ref(&mut context.writer, self)
{
return Ok(());
}
if write_type_info {
T::fory_write_type_info(context)?;
}
T::fory_write_data_generic(self, context, has_generics)
}
}
}
fn fory_write_data_generic(
&self,
context: &mut WriteContext,
has_generics: bool,
) -> Result<(), Error> {
if T::fory_is_shared_ref() {
return Err(Error::not_allowed(
"Arc<T> where T is a shared ref type is not allowed for serialization.",
));
}
T::fory_write_data_generic(&**self, context, has_generics)
}
fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
self.fory_write_data_generic(context, false)
}
fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
T::fory_write_type_info(context)
}
fn fory_read(
context: &mut ReadContext,
ref_mode: RefMode,
read_type_info: bool,
) -> Result<Self, Error> {
read_arc(context, ref_mode, read_type_info, None)
}
fn fory_read_with_type_info(
context: &mut ReadContext,
ref_mode: RefMode,
typeinfo: Rc<TypeInfo>,
) -> Result<Self, Error>
where
Self: Sized + ForyDefault,
{
read_arc(context, ref_mode, false, Some(typeinfo))
}
fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
if T::fory_is_shared_ref() {
return Err(Error::not_allowed(
"Arc<T> where T is a shared ref type is not allowed for deserialization.",
));
}
let inner = T::fory_read_data(context)?;
Ok(Arc::new(inner))
}
fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
T::fory_read_type_info(context)
}
fn fory_reserved_space() -> usize {
4
}
fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
T::fory_get_type_id(type_resolver)
}
fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
match type_resolver.get_type_info(&std::any::TypeId::of::<T>()) {
Ok(info) => Ok(info),
Err(e) => Err(Error::enhance_type_error::<T>(e)),
}
}
fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
(**self).fory_type_id_dyn(type_resolver)
}
fn fory_static_type_id() -> TypeId {
T::fory_static_type_id()
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
fn read_arc<T: Serializer + ForyDefault + 'static>(
context: &mut ReadContext,
ref_mode: RefMode,
read_type_info: bool,
typeinfo: Option<Rc<TypeInfo>>,
) -> Result<Arc<T>, Error> {
match ref_mode {
RefMode::None => {
let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
Ok(Arc::new(inner))
}
RefMode::NullOnly => {
let ref_flag = context.reader.read_i8()?;
if ref_flag == RefFlag::Null as i8 {
return Err(Error::invalid_ref("Arc cannot be null"));
}
let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
Ok(Arc::new(inner))
}
RefMode::Tracking => {
let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
match ref_flag {
RefFlag::Null => Err(Error::invalid_ref("Arc cannot be null")),
RefFlag::Ref => {
let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
context.ref_reader.get_arc_ref::<T>(ref_id).ok_or_else(|| {
Error::invalid_ref(format!("Arc reference {ref_id} not found"))
})
}
RefFlag::NotNullValue => {
let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
Ok(Arc::new(inner))
}
RefFlag::RefValue => {
let ref_id = context.ref_reader.reserve_ref_id();
let inner = read_arc_inner::<T>(context, read_type_info, typeinfo)?;
let arc = Arc::new(inner);
context.ref_reader.store_arc_ref_at(ref_id, arc.clone());
Ok(arc)
}
}
}
}
}
fn read_arc_inner<T: Serializer + ForyDefault + 'static>(
context: &mut ReadContext,
read_type_info: bool,
typeinfo: Option<Rc<TypeInfo>>,
) -> Result<T, Error> {
if let Some(typeinfo) = typeinfo {
return T::fory_read_with_type_info(context, RefMode::None, typeinfo);
}
if read_type_info {
T::fory_read_type_info(context)?;
}
T::fory_read_data(context)
}
impl<T: ForyDefault> ForyDefault for Arc<T> {
fn fory_default() -> Self {
Arc::new(T::fory_default())
}
}