const-type-layout 0.1.0

Derivable const trait to view and compare the layout of a struct, union, or enum.
Documentation
use alloc::fmt;
use core::{marker::PhantomData, ops::Deref};

use crate::{Field, TypeLayoutGraph, TypeLayoutInfo, Variant};

use serde::{
    de::{Error, SeqAccess, Visitor},
    ser::SerializeSeq,
    Deserialize, Deserializer, Serialize, Serializer,
};

pub fn serialize<
    'a,
    F: Deref<Target = [Field<'a>]> + Serialize,
    V: Deref<Target = [Variant<'a, F>]> + Serialize,
    I: Deref<Target = TypeLayoutInfo<'a, F, V>> + Serialize,
    S: Serializer,
>(
    tys: &[Option<I>; TypeLayoutGraph::CAPACITY],
    serializer: S,
) -> Result<S::Ok, S::Error> {
    let mut len = 0;

    let mut it = tys.iter();

    while let Some(Some(_)) = it.next() {
        len += 1;
    }

    let mut seq = serializer.serialize_seq(Some(len))?;

    let mut it = tys.iter();

    while let Some(Some(ty)) = it.next() {
        seq.serialize_element(ty)?;
    }

    seq.end()
}

pub fn deserialize<
    'de,
    F: Deref<Target = [Field<'de>]> + Deserialize<'de>,
    V: Deref<Target = [Variant<'de, F>]> + Deserialize<'de>,
    I: Deref<Target = TypeLayoutInfo<'de, F, V>> + Deserialize<'de>,
    D: Deserializer<'de>,
>(
    deserializer: D,
) -> Result<[Option<I>; TypeLayoutGraph::CAPACITY], D::Error> {
    deserializer.deserialize_seq(TypeListVisitor {
        marker: PhantomData,
    })
}

struct TypeListVisitor<
    'de,
    F: Deref<Target = [Field<'de>]>,
    V: Deref<Target = [Variant<'de, F>]>,
    I: Deref<Target = TypeLayoutInfo<'de, F, V>>,
> {
    marker: PhantomData<(F, V, I)>,
}

impl<
        'de,
        F: Deref<Target = [Field<'de>]> + Deserialize<'de>,
        V: Deref<Target = [Variant<'de, F>]> + Deserialize<'de>,
        I: Deref<Target = TypeLayoutInfo<'de, F, V>> + Deserialize<'de>,
    > Visitor<'de> for TypeListVisitor<'de, F, V, I>
{
    type Value = [Option<I>; TypeLayoutGraph::CAPACITY];

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a sequence")
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: SeqAccess<'de>,
    {
        let mut tys = [(); TypeLayoutGraph::CAPACITY].map(|_| None);

        let mut i = 0;

        while let Some(ty) = seq.next_element()? {
            let Some(slot) = tys.get_mut(i) else {
                return Err(Error::custom(
                    "TypeLayoutGraph is not large enough for this complex type"
                ))
            };

            *slot = Some(ty);

            i += 1;
        }

        Ok(tys)
    }
}