Add macro to build message structs and impls

This commit is contained in:
Patrick Auernig 2018-03-22 18:11:41 +01:00
parent a7e7bb8446
commit 9a9fc504fe
2 changed files with 104 additions and 196 deletions

76
src/macros.rs Normal file
View File

@ -0,0 +1,76 @@
macro_rules! message_func {
[ $name:ident, $type:tt func ] => {
pub fn $name<F: FnOnce($type) -> $type>(mut self, func: F) -> Self {
self.$name = Some(func($type::default())); self
}
};
[ $name:ident, String ] => {
pub fn $name<S: Into<String>>(mut self, value: S) -> Self {
self.$name = Some(value.into()); self
}
};
[ $name:ident, $type:ty ] => {
pub fn $name(mut self, value: $type) -> Self {
self.$name = Some(value); self
}
};
}
macro_rules! message_format {
[ @st ( $name:ident $field:tt: $type:tt alias = $alias:tt, $($rest:tt)* ) -> ( $($out:tt)* ) ] => {
message_format![ @st
( $name $field: $type, $($rest)* ) -> (
#[serde(rename = $alias)]
$($out)*
)
];
};
[ @st ( $name:ident $field:tt: $type:tt func, $($rest:tt)* ) -> ( $($out:tt)* ) ] => {
message_format![ @st ( $name $field: $type, $($rest)* ) -> ( $($out)* ) ];
};
[ @st ( $name:ident $field:ident: $type:ty, $($rest:tt)* ) -> ( $($out:tt)* ) ] => {
message_format![ @st
( $name $($rest)* ) -> (
#[serde(skip_serializing_if = "Option::is_none")]
pub $field: Option<$type>,
$($out)*
)
];
};
[ @st ( $name:ident ) -> ( $($out:tt)* ) ] => {
#[derive(Debug, Default, Serialize)]
pub struct $name { $($out)* }
};
[ @im ( $name:ident $field:ident: $type:tt func, $($rest:tt)* ) -> ( $($out:tt)* ) ] => {
message_format![ @im ( $name $($rest)* ) -> ( message_func![$field, $type func]; $($out)* ) ];
};
[ @im ( $name:ident $field:ident: $type:tt alias = $modifier:tt, $($rest:tt)* ) -> ( $($out:tt)* ) ] => {
message_format![ @im ( $name $field: $type, $($rest)* ) -> ( $($out)* ) ];
};
[ @im ( $name:ident $field:ident: $type:tt, $($rest:tt)* ) -> ( $($out:tt)* ) ] => {
message_format![ @im ( $name $($rest)* ) -> ( message_func![$field, $type]; $($out)* ) ];
};
[ @im ( $name:ident ) -> ( $($out:tt)* ) ] => {
impl $name {
pub fn new() -> Self {
Self::default()
}
$($out)*
}
};
[ $name:ident $($body:tt)* ] => {
message_format![@st ( $name $($body)* ) -> () ];
message_format![@im ( $name $($body)* ) -> () ];
}
}

View File

@ -16,203 +16,35 @@ impl SetActivityArgs {
}
}
#[derive(Debug, Default, Serialize)]
pub struct SetActivity {
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
message_format![SetActivity
state: String,
details: String,
instance: bool,
timestamps: SetActivityTimestamps func,
assets: SetActivityAssets func,
party: SetActivityParty func,
secrets: SetActivitySecrets func,
];
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<String>,
message_format![SetActivityTimestamps
start: u32,
end: u32,
];
#[serde(skip_serializing_if = "Option::is_none")]
pub instance: Option<bool>,
message_format![SetActivityAssets
large_image: String,
large_text: String,
small_image: String,
small_text: String,
];
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamps: Option<ActivityTimestamps>,
message_format![SetActivityParty
id: u32,
size: (u32, u32),
];
#[serde(skip_serializing_if = "Option::is_none")]
pub assets: Option<ActivityAssets>,
#[serde(skip_serializing_if = "Option::is_none")]
pub party: Option<ActivityParty>,
#[serde(skip_serializing_if = "Option::is_none")]
pub secrets: Option<ActivitySecrets>,
}
impl SetActivity {
pub fn new() -> Self {
Self::default()
}
pub fn state<S>(mut self, s: S) -> Self
where S: Into<String>
{
self.state = Some(s.into());
self
}
pub fn details<S>(mut self, d: S) -> Self
where S: Into<String>
{
self.details = Some(d.into());
self
}
pub fn instance(mut self, i: bool) -> Self {
self.instance = Some(i);
self
}
pub fn timestamps<F>(mut self, f: F) -> Self
where F: FnOnce(ActivityTimestamps) -> ActivityTimestamps
{
self.timestamps = Some(f(ActivityTimestamps::default()));
self
}
pub fn assets<F>(mut self, f: F) -> Self
where F: FnOnce(ActivityAssets) -> ActivityAssets
{
self.assets = Some(f(ActivityAssets::default()));
self
}
pub fn party<F>(mut self, f: F) -> Self
where F: FnOnce(ActivityParty) -> ActivityParty
{
self.party = Some(f(ActivityParty::default()));
self
}
pub fn secrets<F>(mut self, f: F) -> Self
where F: FnOnce(ActivitySecrets) -> ActivitySecrets
{
self.secrets = Some(f(ActivitySecrets::default()));
self
}
}
#[derive(Debug, Default, Serialize)]
pub struct ActivityTimestamps {
#[serde(skip_serializing_if = "Option::is_none")]
pub start: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end: Option<u32>,
}
impl ActivityTimestamps {
pub fn start(mut self, i: u32) -> Self {
self.start = Some(i);
self
}
pub fn end(mut self, i: u32) -> Self {
self.end = Some(i);
self
}
}
#[derive(Debug, Default, Serialize)]
pub struct ActivityAssets {
#[serde(skip_serializing_if = "Option::is_none")]
pub large_image: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub large_text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub small_image: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub small_text: Option<String>,
}
impl ActivityAssets {
pub fn large_image<S>(mut self, i: S) -> Self
where S: Into<String>
{
self.large_image = Some(i.into());
self
}
pub fn large_text<S>(mut self, t: S) -> Self
where S: Into<String>
{
self.large_text = Some(t.into());
self
}
pub fn small_image<S>(mut self, i: S) -> Self
where S: Into<String>
{
self.small_image = Some(i.into());
self
}
pub fn small_text<S>(mut self, t: S) -> Self
where S: Into<String>
{
self.small_text = Some(t.into());
self
}
}
#[derive(Debug, Default, Serialize)]
pub struct ActivityParty {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<[u32; 2]>,
}
impl ActivityParty {
pub fn id(mut self, i: u32) -> Self {
self.id = Some(i);
self
}
pub fn size(mut self, current: u32, max: u32) -> Self {
self.size = Some([current, max]);
self
}
}
#[derive(Debug, Default, Serialize)]
pub struct ActivitySecrets {
#[serde(skip_serializing_if = "Option::is_none")]
pub join: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub spectate: Option<String>,
// NOTE: think of a better name for this
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "match")]
pub shoubu: Option<String>,
}
impl ActivitySecrets {
pub fn join<S>(mut self, secret: S) -> Self
where S: Into<String>
{
self.join = Some(secret.into());
self
}
pub fn spectate<S>(mut self, secret: S) -> Self
where S: Into<String>
{
self.spectate = Some(secret.into());
self
}
pub fn game<S>(mut self, secret: S) -> Self
where S: Into<String>
{
self.shoubu = Some(secret.into());
self
}
}
message_format![SetActivitySecrets
join: String,
spectate: String,
game: String alias = "match",
];