use crate::ensure;
use crate::error::Error;
use crate::meta::FieldInfo;
use crate::resolver::context::{ReadContext, WriteContext};
use crate::serializer::{ForyDefault, Serializer};
use crate::types::{RefFlag, RefMode, TypeId};
use crate::TypeResolver;
#[inline(always)]
pub fn actual_type_id(_type_id: u32, register_by_name: bool, _compatible: bool) -> u32 {
if register_by_name {
TypeId::NAMED_ENUM as u32
} else {
TypeId::ENUM as u32
}
}
#[inline(always)]
pub fn write<T: Serializer>(
this: &T,
context: &mut WriteContext,
ref_mode: RefMode,
write_type_info: bool,
) -> Result<(), Error> {
if ref_mode != RefMode::None {
context.writer.write_i8(RefFlag::NotNullValue as i8);
}
if write_type_info {
T::fory_write_type_info(context)?;
}
this.fory_write_data(context)
}
#[inline(always)]
pub fn write_type_info<T: Serializer>(context: &mut WriteContext) -> Result<(), Error> {
let type_id = T::fory_get_type_id(context.get_type_resolver())?;
context.writer.write_u8(type_id as u8);
let rs_type_id = std::any::TypeId::of::<T>();
if type_id == TypeId::ENUM {
let type_info = context.get_type_resolver().get_type_info(&rs_type_id)?;
context
.writer
.write_var_uint32(type_info.get_user_type_id());
return Ok(());
}
if context.is_share_meta() {
context.write_type_meta(rs_type_id)?;
} else {
let type_info = context.get_type_resolver().get_type_info(&rs_type_id)?;
let namespace = type_info.get_namespace();
let type_name = type_info.get_type_name();
context.write_meta_string_bytes(namespace)?;
context.write_meta_string_bytes(type_name)?;
}
Ok(())
}
#[inline(always)]
pub fn read<T: Serializer + ForyDefault>(
context: &mut ReadContext,
ref_mode: RefMode,
read_type_info: bool,
) -> Result<T, Error> {
let ref_flag = if ref_mode != RefMode::None {
context.reader.read_i8()?
} else {
RefFlag::NotNullValue as i8
};
if ref_flag == RefFlag::Null as i8 {
Ok(T::fory_default())
} else if ref_flag == (RefFlag::NotNullValue as i8) || ref_flag == (RefFlag::RefValue as i8) {
if read_type_info {
T::fory_read_type_info(context)?;
}
T::fory_read_data(context)
} else if ref_flag == (RefFlag::Ref as i8) {
Err(Error::invalid_ref("Invalid ref, enum type is not a ref"))
} else {
Err(Error::invalid_data(format!(
"Unknown ref flag: {}",
ref_flag
)))
}
}
#[inline(always)]
pub fn read_type_info<T: Serializer>(context: &mut ReadContext) -> Result<(), Error> {
let local_type_id = T::fory_get_type_id(context.get_type_resolver())?;
let remote_type_id = context.reader.read_u8()?;
ensure!(
local_type_id as u8 == remote_type_id,
Error::type_mismatch(local_type_id as u32, remote_type_id as u32)
);
if remote_type_id == TypeId::NAMED_ENUM as u8 {
if context.is_share_meta() {
let _type_info = context.read_type_meta()?;
} else {
let _namespace_msb = context.read_meta_string()?;
let _type_name_msb = context.read_meta_string()?;
}
} else {
context.reader.read_varuint32()?;
}
Ok(())
}
pub trait NamedEnumVariantMetaTrait: 'static {
fn fory_get_sorted_field_names() -> &'static [&'static str] {
&[]
}
#[allow(unused_variables)]
fn fory_fields_info(type_resolver: &TypeResolver) -> Result<Vec<FieldInfo>, Error> {
Ok(Vec::default())
}
}