interoptopus 0.16.0

The polyglot bindings generator for your library (C#, C, Python, ...). 🐙
Documentation
use crate::inventory::Inventory;
use crate::lang::meta::{Docs, Emission, Visibility};
use crate::lang::types::wire::WireIO;
use crate::lang::types::{Type, TypeId, TypeInfo, TypeKind};
use crate::wire::SerializationError;
use std::io::{Read, Write};
use std::mem::MaybeUninit;

/// A fixed-size array type `[T; N]`.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Array {
    /// The element type.
    pub ty: TypeId,
    /// The array length.
    pub len: usize,
}

unsafe impl<T, const N: usize> TypeInfo for [T; N]
where
    T: TypeInfo + Copy,
{
    const WIRE_SAFE: bool = T::WIRE_SAFE;
    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 {
        // Reliably derive an ID for an array of type T and length N.
        T::id().derive(0x06A3676E231857123975EA87924CA277).derive(N as u128)
    }

    fn kind() -> TypeKind {
        TypeKind::Array(Array { ty: T::id(), len: N })
    }

    fn ty() -> Type {
        Type { emission: Emission::Builtin, docs: Docs::empty(), visibility: Visibility::Public, name: format!("[{}; {N}]", T::ty().name), kind: Self::kind() }
    }

    fn register(inventory: &mut impl Inventory) {
        // Ensure base type is registered.
        T::register(inventory);

        inventory.register_type(Self::id(), Self::ty());
    }
}

unsafe impl<T, const N: usize> WireIO for [T; N]
where
    T: WireIO + Copy,
{
    fn write(&self, out: &mut impl Write) -> Result<(), SerializationError> {
        for x in self {
            x.write(out)?;
        }
        Ok(())
    }

    fn read(input: &mut impl Read) -> Result<Self, SerializationError> {
        let mut rval = [MaybeUninit::uninit(); N];

        for x in &mut rval {
            x.write(T::read(input)?);
        }

        Ok(unsafe { std::mem::transmute_copy(&rval) })
    }

    fn live_size(&self) -> usize {
        self.iter().map(WireIO::live_size).sum()
    }
}