use crate::ensure;
use crate::error::Error;
use crate::resolver::context::ReadContext;
use crate::resolver::context::WriteContext;
use crate::serializer::Serializer;
use crate::types::TypeId;
pub fn fory_write_data<T: Serializer>(this: &[T], context: &mut WriteContext) -> Result<(), Error> {
if context.is_xlang() {
match T::fory_static_type_id() {
TypeId::U128 => {
return Err(Error::not_allowed(
"u128 is not supported in cross-language mode",
));
}
TypeId::INT128 => {
return Err(Error::not_allowed(
"i128 is not supported in cross-language mode",
));
}
TypeId::USIZE => {
return Err(Error::not_allowed(
"usize is not supported in cross-language mode",
));
}
TypeId::ISIZE => {
return Err(Error::not_allowed(
"isize is not supported in cross-language mode",
));
}
_ => {}
}
}
let len_bytes = std::mem::size_of_val(this);
context.writer.write_var_uint32(len_bytes as u32);
if !this.is_empty() {
#[cfg(target_endian = "little")]
{
unsafe {
let ptr = this.as_ptr() as *const u8;
let slice = std::slice::from_raw_parts(ptr, len_bytes);
context.writer.write_bytes(slice);
}
}
#[cfg(target_endian = "big")]
{
for item in this {
item.write(context)?;
}
}
}
Ok(())
}
pub fn fory_write_type_info(context: &mut WriteContext, type_id: TypeId) -> Result<(), Error> {
context.writer.write_u8(type_id as u8);
Ok(())
}
pub fn fory_read_data<T: Serializer>(context: &mut ReadContext) -> Result<Vec<T>, Error> {
let size_bytes = context.reader.read_varuint32()? as usize;
if size_bytes % std::mem::size_of::<T>() != 0 {
return Err(Error::invalid_data("Invalid data length"));
}
let remaining = context.reader.slice_after_cursor().len();
if size_bytes > remaining {
let cursor = context.reader.get_cursor();
return Err(Error::buffer_out_of_bound(
cursor,
size_bytes,
cursor + remaining,
));
}
let len = size_bytes / std::mem::size_of::<T>();
let mut vec: Vec<T> = Vec::with_capacity(len);
#[cfg(target_endian = "little")]
{
unsafe {
let dst_ptr = vec.as_mut_ptr() as *mut u8;
let src = context.reader.read_bytes(size_bytes)?;
std::ptr::copy_nonoverlapping(src.as_ptr(), dst_ptr, size_bytes);
vec.set_len(len);
}
}
#[cfg(target_endian = "big")]
{
for _ in 0..len {
vec.push(T::read(context)?);
}
}
Ok(vec)
}
pub fn fory_read_type_info(context: &mut ReadContext, type_id: TypeId) -> Result<(), Error> {
let remote_type_id = context.reader.read_u8()? as u32;
if remote_type_id == TypeId::LIST as u32 {
return Err(Error::type_error(
"Vec<number> belongs to the `number_array` type, \
and Vec<Option<number>> belongs to the `list` type. \
You should not read data of type `list` as data of type `number_array`.",
));
}
let local_type_id = type_id as u32;
ensure!(
local_type_id == remote_type_id,
Error::type_mismatch(local_type_id, remote_type_id)
);
Ok(())
}
pub fn fory_reserved_space<T>() -> usize {
std::mem::size_of::<T>()
}