macro_rules! impl_control_builtin {
( $control:ident <$payload:ty> {
$($builtin:ident => $control_fun:path),+
}
) => {
impl_control_builtin!{
@base $control <$payload> {
$($builtin => $control_fun),+
}
}
impl std::convert::TryFrom <$control> for Builtin {
type Error = $control;
fn try_from ($control (index) : $control) -> std::result::Result <Self, $control> {
Builtin::from_repr (index).ok_or ($control (index))
}
}
impl From <Builtin> for $control {
fn from (builtin : Builtin) -> Self {
$control (builtin as $crate::interface::controller::controls::ReprType)
}
}
impl From <Builtin> for $crate::interface::controller::controls::Fun <$payload> {
fn from (builtin : Builtin) -> Self {
match builtin {
$(Builtin::$builtin =>
$crate::interface::controller::controls::Fun ($control_fun)
),+
}
}
}
};
( $control:ident <$payload:ty> { /*nil*/ }
) => {
impl_control_builtin!{
@base $control <$payload> { }
}
impl std::convert::TryFrom <$control> for Builtin {
type Error = $control;
fn try_from (control : $control) -> std::result::Result <Self, $control> {
Err (control)
}
}
impl From <Builtin> for $control {
fn from (_ : Builtin) -> Self {
unreachable!()
}
}
impl From <Builtin> for $crate::interface::controller::controls::Fun <$payload> {
fn from (_ : Builtin) -> Self {
unreachable!()
}
}
};
( @base
$control:ident <$payload:ty> {
$($builtin:ident => $control_fun:path),*
}
) => {
impl_control_builtin!{
@base_enum $control <$payload> { $($builtin => $control_fun),* }
}
#[doc = "Concrete extensible "]
#[doc = stringify!($control)]
#[doc = " control callback index"]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd,
$crate::serde::Deserialize, $crate::serde::Serialize)]
pub struct $control (pub $crate::interface::controller::controls::ReprType);
impl $crate::interface::controller::controls::Control for $control {
type Payload = $payload;
type Builtin = Builtin;
}
impl From <$crate::interface::controller::controls::ReprType> for $control {
fn from (index : $crate::interface::controller::controls::ReprType) -> Self {
$control (index)
}
}
impl AsRef <$crate::interface::controller::controls::ReprType> for $control {
fn as_ref (&self) -> &$crate::interface::controller::controls::ReprType {
&self.0
}
}
impl $crate::interface::controller::controls::Id <$control> for Builtin { }
impl $crate::interface::controller::controls::Id <$control> for
$crate::interface::controller::controls::Nil { }
impl From <$crate::interface::controller::controls::Nil> for $control {
fn from (_ : $crate::interface::controller::controls::Nil) -> Self {
unreachable!()
}
}
impl std::convert::TryFrom <$control> for
$crate::interface::controller::controls::Nil
{
type Error = $control;
fn try_from (control : $control) -> std::result::Result <Self, $control> {
Err (control)
}
}
};
( @base_enum
$control:ident <$payload:ty> { }
) => {
#[doc = "Built-in "]
#[doc = stringify!($control)]
#[doc = " control IDs"]
#[derive(Clone, Debug, Eq, PartialEq,
$crate::strum::EnumCount, $crate::strum::FromRepr,
$crate::serde::Deserialize, $crate::serde::Serialize)]
pub enum Builtin { }
};
( @base_enum
$control:ident <$payload:ty> {
$($builtin:ident => $control_fun:path),*
}
) => {
#[doc = "Built-in "]
#[doc = stringify!($control)]
#[doc = " control IDs"]
#[derive(Clone, Debug, Eq, PartialEq,
$crate::strum::EnumCount, $crate::strum::FromRepr,
$crate::serde::Deserialize, $crate::serde::Serialize)]
#[repr(u16)]
pub enum Builtin {
$($builtin),*
}
}
}
#[macro_export]
macro_rules! extend_control {
( $extended:ident <$payload:ty> ($($control_path:ident)::+, $control:ident) {
$first:ident => $first_fun:path
$(, $variant:ident => $extended_fun:path)*
}
) => {
#[derive(Clone, Debug, Eq, PartialEq, $crate::strum::FromRepr,
$crate::serde::Deserialize, $crate::serde::Serialize)]
#[repr(u16)]
pub enum $extended {
$first = <
<$($control_path)::+::$control
as $crate::interface::controller::controls::Control>::Builtin
as $crate::strum::EnumCount
>::COUNT as $crate::interface::controller::controls::ReprType
$(, $variant)*
}
impl $crate::interface::controller::controls::Id <$($control_path)::+::$control>
for $extended { }
impl std::convert::TryFrom <$($control_path)::+::$control> for $extended {
type Error = $($control_path)::+::$control;
fn try_from (id : $($control_path)::+::$control)
-> std::result::Result <Self, $($control_path)::+::$control>
{
Self::from_repr (*id.as_ref()).ok_or (id)
}
}
impl From <$extended> for $($control_path)::+::$control {
fn from (control : $extended) -> Self {
$($control_path)::+::$control::from (
control as $crate::interface::controller::controls::ReprType
)
}
}
impl From <$extended> for $($control_path)::+::Control <$extended> {
fn from (extended : $extended) -> Self {
$($control_path)::+::Control (extended.into(), Default::default())
}
}
impl From <$extended> for $crate::interface::controller::controls::Fun <$payload> {
fn from (control : $extended) -> Self {
match control {
$extended::$first =>
$crate::interface::controller::controls::Fun ($first_fun)
$(,
$extended::$variant =>
$crate::interface::controller::controls::Fun ($extended_fun)
)*
}
}
}
}
}
macro_rules! impl_control_serdes {
($control:ident) => {
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Control <E :
$crate::interface::controller::controls::Id <$control> =
$crate::interface::controller::controls::Nil
> (pub $control, pub std::marker::PhantomData <E>);
impl <E : $crate::interface::controller::controls::Id <$control>>
From <$control> for Control <E>
{
fn from (control : $control) -> Self {
Control (control, Default::default())
}
}
impl <E : $crate::interface::controller::controls::Id <$control>>
From <Control <E>> for $control
{
fn from (binding : Control <E>) -> Self {
binding.0
}
}
impl <E : $crate::interface::controller::controls::Id <$control>>
From <Builtin> for Control <E>
{
fn from (builtin : Builtin) -> Self {
Control (builtin.into(), Default::default())
}
}
struct ControlVisitor <E :
$crate::interface::controller::controls::Id <$control> =
$crate::interface::controller::controls::Nil
> (std::marker::PhantomData <E>);
impl <E : $crate::interface::controller::controls::Id <$control>>
serde::Serialize for Control <E>
{
fn serialize <S : serde::Serializer> (&self, serializer : S)
-> std::result::Result <S::Ok, S::Error>
{
use std::convert::TryFrom;
use serde::ser::Error;
let control = if let Ok (builtin) = Builtin::try_from (self.0.clone()) {
serde_plain::to_string (&builtin).unwrap()
} else if let Ok (application) = E::try_from (self.0.clone()) {
serde_plain::to_string (&application).unwrap()
} else {
return Err (S::Error::custom (format!("invalid control index: {:?}", self.0)))
};
serializer.serialize_str(&control)
}
}
impl <E : $crate::interface::controller::controls::Id <$control>>
serde::de::Visitor <'_> for ControlVisitor <E>
{
type Value = Control <E>;
fn expecting (&self, formatter : &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str ("A control identifier")
}
fn visit_str <ERR : serde::de::Error> (self, value : &str)
-> std::result::Result <Self::Value, ERR>
{
let control = if let Ok (builtin) = serde_plain::from_str::<Builtin> (value) {
builtin.into()
} else if let Ok (application) = serde_plain::from_str::<E> (value) {
application.into()
} else {
return Err (ERR::custom (format!("invalid control identifier: {:?}", value)))
};
Ok (Control (control, Default::default()))
}
}
impl <'de, E : $crate::interface::controller::controls::Id <$control>>
serde::Deserialize <'de> for Control <E>
{
fn deserialize <D : serde::Deserializer <'de>> (deserializer : D)
-> std::result::Result <Self, D::Error>
{
deserializer.deserialize_str (ControlVisitor (Default::default()))
}
}
}
}