use crate::bad_wire;
use crate::inventory::Inventory;
use crate::lang::meta::{Docs, Emission, FileEmission, Visibility};
use crate::lang::types::wire::WireIO;
use crate::lang::types::{Type, TypeId, TypeInfo, TypeKind, TypePattern, WireOnly};
use crate::wire::SerializationError;
use std::collections::HashMap;
use std::io::{Read, Write};
use std::mem::MaybeUninit;
macro_rules! impl_ptr {
($t:ty, $name:expr, $kind:tt, $id:expr, option_ptr_safe = $ops:expr) => {
unsafe impl<T: TypeInfo> TypeInfo for $t {
const WIRE_SAFE: bool = false;
const RAW_SAFE: bool = T::RAW_SAFE;
const ASYNC_SAFE: bool = false;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
const OPTION_PTR_SAFE: bool = $ops;
fn id() -> TypeId {
T::id().derive($id)
}
fn kind() -> TypeKind {
TypeKind::$kind(T::id())
}
fn ty() -> Type {
Type { emission: Emission::Builtin, docs: Docs::empty(), visibility: Visibility::Public, name: $name.to_string(), kind: Self::kind() }
}
fn register(inventory: &mut impl Inventory) {
T::register(inventory);
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl<T: WireIO> WireIO for $t {
fn write(&self, _: &mut impl Write) -> Result<(), SerializationError> {
bad_wire!()
}
fn read(_: &mut impl Read) -> Result<Self, SerializationError> {
bad_wire!()
}
fn live_size(&self) -> usize {
bad_wire!()
}
}
};
}
impl_ptr!(std::ptr::NonNull<T>, "*mut T", ReadWritePointer, 0x7EE1DB481C7FEAD63EB329E9812A2F68, option_ptr_safe = true);
impl_ptr!(&'_ mut T, "*mut T", ReadWritePointer, 0x7EE1DB481C7FEAD63EB329E9812A2F68, option_ptr_safe = true);
impl_ptr!(*mut T, "*mut T", ReadWritePointer, 0x7EE1DB481C7FEAD63EB329E9812A2F68, option_ptr_safe = false);
impl_ptr!(&'_ T, "*const T", ReadPointer, 0x20973BD3D67EF4E0323195B99A01FD5E, option_ptr_safe = true);
impl_ptr!(*const T, "*const T", ReadPointer, 0x20973BD3D67EF4E0323195B99A01FD5E, option_ptr_safe = false);
#[must_use]
pub fn type_id_ptr(x: TypeId) -> TypeId {
x.derive(0x20973BD3D67EF4E0323195B99A01FD5E)
}
#[must_use]
pub fn type_id_ptr_mut(x: TypeId) -> TypeId {
x.derive(0x7EE1DB481C7FEAD63EB329E9812A2F68)
}
unsafe impl<T: TypeInfo> TypeInfo for MaybeUninit<T> {
const WIRE_SAFE: bool = false;
const RAW_SAFE: bool = T::RAW_SAFE;
const ASYNC_SAFE: bool = T::ASYNC_SAFE;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
fn id() -> TypeId {
T::id()
}
fn kind() -> TypeKind {
T::kind()
}
fn ty() -> Type {
T::ty()
}
fn register(inventory: &mut impl Inventory) {
T::register(inventory);
}
}
unsafe impl<T: WireIO> WireIO for MaybeUninit<T> {
fn write(&self, _: &mut impl Write) -> Result<(), SerializationError> {
bad_wire!()
}
fn read(_: &mut impl Read) -> Result<Self, SerializationError> {
bad_wire!()
}
fn live_size(&self) -> usize {
bad_wire!()
}
}
unsafe impl TypeInfo for String {
const WIRE_SAFE: bool = true;
const RAW_SAFE: bool = false;
const ASYNC_SAFE: bool = false;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
fn id() -> TypeId {
TypeId::new(0x121F9B85DF8484C54AFC97C4C345A715)
}
fn kind() -> TypeKind {
TypeKind::WireOnly(WireOnly::String)
}
fn ty() -> Type {
Type {
emission: Emission::FileEmission(FileEmission::Common),
docs: Docs::empty(),
visibility: Visibility::Public,
name: "String".to_string(),
kind: Self::kind(),
}
}
fn register(inventory: &mut impl Inventory) {
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl WireIO for String {
fn write(&self, out: &mut impl Write) -> Result<(), SerializationError> {
u32::try_from(self.len())?.write(out)?;
out.write_all(self.as_bytes())?;
Ok(())
}
fn read(input: &mut impl Read) -> Result<Self, SerializationError> {
let len = u32::read(input)? as usize;
let mut buf = vec![0u8; len];
input.read_exact(&mut buf)?;
Self::from_utf8(buf).map_err(|e| SerializationError::new(e.to_string()))
}
fn live_size(&self) -> usize {
4 + self.len()
}
}
unsafe impl<T: TypeInfo> TypeInfo for Vec<T> {
const WIRE_SAFE: bool = T::WIRE_SAFE;
const RAW_SAFE: bool = false;
const ASYNC_SAFE: bool = false;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
fn id() -> TypeId {
T::id().derive(0x3D4A1327D939CFFCC50EC62B7190BDE0)
}
fn kind() -> TypeKind {
TypeKind::WireOnly(WireOnly::Vec(T::id()))
}
fn ty() -> Type {
let t = T::ty();
Type { emission: Emission::Builtin, docs: Docs::empty(), visibility: Visibility::Public, name: format!("Vec<{}>", t.name), kind: Self::kind() }
}
fn register(inventory: &mut impl Inventory) {
T::register(inventory);
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl<T: WireIO> WireIO for Vec<T> {
fn write(&self, out: &mut impl Write) -> Result<(), SerializationError> {
u32::try_from(self.len())?.write(out)?;
for item in self {
item.write(out)?;
}
Ok(())
}
fn read(input: &mut impl Read) -> Result<Self, SerializationError> {
let len = u32::read(input)? as usize;
let mut vec = Self::with_capacity(len);
for _ in 0..len {
vec.push(T::read(input)?);
}
Ok(vec)
}
fn live_size(&self) -> usize {
4 + self.iter().map(WireIO::live_size).sum::<usize>()
}
}
unsafe impl<K: TypeInfo, V: TypeInfo, S: ::std::hash::BuildHasher> TypeInfo for HashMap<K, V, S> {
const WIRE_SAFE: bool = K::WIRE_SAFE && V::WIRE_SAFE;
const RAW_SAFE: bool = false;
const ASYNC_SAFE: bool = false;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
fn id() -> TypeId {
TypeId::new(0xB55DC9DFF8B775E03D34267E9F1DABE5).derive_id(K::id()).derive_id(V::id())
}
fn kind() -> TypeKind {
TypeKind::WireOnly(WireOnly::Map(K::id(), V::id()))
}
fn ty() -> Type {
let k = K::ty();
let v = V::ty();
Type { emission: Emission::Builtin, docs: Docs::empty(), visibility: Visibility::Public, name: format!("HashMap<{}, {}>", k.name, v.name), kind: Self::kind() }
}
fn register(inventory: &mut impl Inventory) {
K::register(inventory);
V::register(inventory);
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl<K: WireIO + Eq + core::hash::Hash, V: WireIO, S: ::std::hash::BuildHasher + Default> WireIO for HashMap<K, V, S> {
fn write(&self, out: &mut impl Write) -> Result<(), SerializationError> {
u32::try_from(self.len())?.write(out)?;
for (k, v) in self {
k.write(out)?;
v.write(out)?;
}
Ok(())
}
fn read(input: &mut impl Read) -> Result<Self, SerializationError> {
let len = u32::read(input)? as usize;
let mut map = Self::with_capacity_and_hasher(len, Default::default());
for _ in 0..len {
let k = K::read(input)?;
let v = V::read(input)?;
map.insert(k, v);
}
Ok(map)
}
fn live_size(&self) -> usize {
4 + self.iter().map(|(k, v)| k.live_size() + v.live_size()).sum::<usize>()
}
}
unsafe impl TypeInfo for ::std::ffi::c_void {
const WIRE_SAFE: bool = false;
const RAW_SAFE: bool = true;
const ASYNC_SAFE: bool = true;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
fn id() -> TypeId {
TypeId::new(0x34E7C243AFCBE5D699605695ACF663B5)
}
fn kind() -> TypeKind {
TypeKind::TypePattern(TypePattern::CVoid)
}
fn ty() -> Type {
Type { emission: Emission::Builtin, docs: Docs::empty(), visibility: Visibility::Public, name: "c_void".to_string(), kind: Self::kind() }
}
fn register(inventory: &mut impl Inventory) {
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl WireIO for ::std::ffi::c_void {
fn write(&self, _: &mut impl Write) -> Result<(), SerializationError> {
bad_wire!()
}
fn read(_: &mut impl Read) -> Result<Self, SerializationError> {
bad_wire!()
}
fn live_size(&self) -> usize {
bad_wire!()
}
}
macro_rules! impl_tuple_wireio {
( $( $name:ident )+ ) => {
#[allow(non_snake_case)]
unsafe impl<$($name: WireIO),+> WireIO for ($($name,)+)
{
fn write(&self, out: &mut impl Write) -> Result<(), SerializationError> {
let ($($name,)+) = self;
$(
$name.write(out)?;
)+
Ok(())
}
fn read(input: &mut impl Read) -> Result<Self, SerializationError> {
Ok((
$(
$name::read(input)?,
)+
))
}
fn live_size(&self) -> usize {
let ($($name,)+) = self;
0 $(
+ $name.live_size()
)+
}
}
};
}
impl_tuple_wireio! { A }
impl_tuple_wireio! { A B }
impl_tuple_wireio! { A B C }
impl_tuple_wireio! { A B C D }
impl_tuple_wireio! { A B C D E }
impl_tuple_wireio! { A B C D E F }
impl_tuple_wireio! { A B C D E F G }
impl_tuple_wireio! { A B C D E F G H }
impl_tuple_wireio! { A B C D E F G H I }
impl_tuple_wireio! { A B C D E F G H I J }
impl_tuple_wireio! { A B C D E F G H I J K }
impl_tuple_wireio! { A B C D E F G H I J K L }
unsafe impl<T: TypeInfo> TypeInfo for Option<T> {
const WIRE_SAFE: bool = true;
const RAW_SAFE: bool = T::OPTION_PTR_SAFE;
const ASYNC_SAFE: bool = false;
const SERVICE_SAFE: bool = T::OPTION_PTR_SAFE;
const SERVICE_CTOR_SAFE: bool = T::OPTION_PTR_SAFE;
fn id() -> TypeId {
if T::OPTION_PTR_SAFE {
T::id()
} else {
TypeId::new(0x2A26D428DCB3A7DFECEC0F0D3154C680).derive_id(T::id())
}
}
fn kind() -> TypeKind {
if T::OPTION_PTR_SAFE {
T::kind()
} else {
TypeKind::WireOnly(WireOnly::Option(T::id()))
}
}
fn ty() -> Type {
if T::OPTION_PTR_SAFE {
T::ty()
} else {
let t = T::ty();
Type { emission: Emission::Builtin, docs: Docs::empty(), visibility: Visibility::Public, name: format!("Option<{}>", t.name), kind: Self::kind() }
}
}
fn register(inventory: &mut impl Inventory) {
T::register(inventory);
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl<T: WireIO> WireIO for Option<T> {
fn write(&self, out: &mut impl Write) -> Result<(), SerializationError> {
match self {
None => 0u8.write(out),
Some(v) => {
1u8.write(out)?;
v.write(out)
}
}
}
fn read(input: &mut impl Read) -> Result<Self, SerializationError>
where
Self: Sized,
{
match u8::read(input)? {
0 => Ok(None),
_ => Ok(Some(T::read(input)?)),
}
}
fn live_size(&self) -> usize {
1 + self.as_ref().map_or(0, WireIO::live_size)
}
}