use crate::signature::{SignatureBuilder, SignatureError};
use crate::ty::{Aligned, Marker};
use crate::{Body, Result};
mod sealed {
pub trait Sealed {}
}
#[non_exhaustive]
pub enum Empty {}
pub trait Fields: self::sealed::Sealed + Marker {
#[doc(hidden)]
type First;
#[doc(hidden)]
type Remaining;
}
impl self::sealed::Sealed for () {}
impl crate::ty::aligned::sealed::Sealed for () {}
impl Aligned for () {
type Alignment = u64;
}
impl crate::ty::marker::sealed::Sealed for () {}
impl Marker for () {
type Return<'de> = ();
#[inline]
fn load_struct<'de>(_: &mut Body<'de>) -> Result<Self::Return<'de>> {
Ok(())
}
#[inline]
fn write_signature(_: &mut SignatureBuilder) -> Result<(), SignatureError> {
Ok(())
}
}
impl Fields for () {
type First = Empty;
type Remaining = ();
}
macro_rules! struct_fields {
($first:ident $(, $rest:ident)*) => {
impl<$first, $($rest),*> self::sealed::Sealed for ($first, $($rest),*)
where
$first: Marker,
$($rest: Marker,)*
{
}
impl<$first, $($rest),*> super::aligned::sealed::Sealed for ($first, $($rest),*) {
}
impl<$first, $($rest),*> Aligned for ($first, $($rest),*)
where
$first: Marker,
$($rest: Marker,)*
{
type Alignment = u64;
}
impl<$first, $($rest),*> super::marker::sealed::Sealed for ($first, $($rest),*)
where
$first: Marker,
$($rest: Marker,)* {
}
impl<$first, $($rest),*> Marker for ($first, $($rest),*)
where
$first: Marker,
$($rest: Marker,)*
{
type Return<'de> = ($first::Return<'de>, $($rest::Return<'de>,)*);
#[inline]
fn load_struct<'de>(buf: &mut Body<'de>) -> Result<Self::Return<'de>> {
Ok((<$first>::load_struct(buf)?, $(<$rest>::load_struct(buf)? ,)*))
}
#[inline]
fn write_signature(signature: &mut SignatureBuilder) -> Result<(), SignatureError> {
signature.open_struct()?;
<$first>::write_signature(signature)?;
$(<$rest>::write_signature(signature)?;)*
signature.close_struct()?;
Ok(())
}
}
impl<$first, $($rest),*> Fields for ($first, $($rest),*)
where
$first: Marker,
$($rest: Marker,)*
{
type First = _A;
type Remaining = ($($rest,)*);
}
}
}
repeat!(struct_fields);