From 9a9fc504fef72ce4e6dab9e8962ac73ce0853477 Mon Sep 17 00:00:00 2001 From: Patrick Auernig Date: Thu, 22 Mar 2018 18:11:41 +0100 Subject: [PATCH] Add macro to build message structs and impls --- src/macros.rs | 76 +++++++++++++ src/models/set_activity.rs | 224 +++++-------------------------------- 2 files changed, 104 insertions(+), 196 deletions(-) create mode 100644 src/macros.rs diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..a9eb376 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,76 @@ +macro_rules! message_func { + [ $name:ident, $type:tt func ] => { + pub fn $name $type>(mut self, func: F) -> Self { + self.$name = Some(func($type::default())); self + } + }; + + [ $name:ident, String ] => { + pub fn $name>(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)* ) -> () ]; + } +} diff --git a/src/models/set_activity.rs b/src/models/set_activity.rs index 9b933d9..ef6ab5d 100644 --- a/src/models/set_activity.rs +++ b/src/models/set_activity.rs @@ -16,203 +16,35 @@ impl SetActivityArgs { } } -#[derive(Debug, Default, Serialize)] -pub struct SetActivity { - #[serde(skip_serializing_if = "Option::is_none")] - pub state: Option, +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, +message_format![SetActivityTimestamps + start: u32, + end: u32, +]; - #[serde(skip_serializing_if = "Option::is_none")] - pub instance: Option, +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, +message_format![SetActivityParty + id: u32, + size: (u32, u32), +]; - #[serde(skip_serializing_if = "Option::is_none")] - pub assets: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub party: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub secrets: Option, -} - -impl SetActivity { - pub fn new() -> Self { - Self::default() - } - - pub fn state(mut self, s: S) -> Self - where S: Into - { - self.state = Some(s.into()); - self - } - - pub fn details(mut self, d: S) -> Self - where S: Into - { - self.details = Some(d.into()); - self - } - - pub fn instance(mut self, i: bool) -> Self { - self.instance = Some(i); - self - } - - pub fn timestamps(mut self, f: F) -> Self - where F: FnOnce(ActivityTimestamps) -> ActivityTimestamps - { - self.timestamps = Some(f(ActivityTimestamps::default())); - self - } - - pub fn assets(mut self, f: F) -> Self - where F: FnOnce(ActivityAssets) -> ActivityAssets - { - self.assets = Some(f(ActivityAssets::default())); - self - } - - pub fn party(mut self, f: F) -> Self - where F: FnOnce(ActivityParty) -> ActivityParty - { - self.party = Some(f(ActivityParty::default())); - self - } - - pub fn secrets(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, - - #[serde(skip_serializing_if = "Option::is_none")] - pub end: Option, -} - -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, - - #[serde(skip_serializing_if = "Option::is_none")] - pub large_text: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub small_image: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - pub small_text: Option, -} - -impl ActivityAssets { - pub fn large_image(mut self, i: S) -> Self - where S: Into - { - self.large_image = Some(i.into()); - self - } - - pub fn large_text(mut self, t: S) -> Self - where S: Into - { - self.large_text = Some(t.into()); - self - } - - pub fn small_image(mut self, i: S) -> Self - where S: Into - { - self.small_image = Some(i.into()); - self - } - - pub fn small_text(mut self, t: S) -> Self - where S: Into - { - self.small_text = Some(t.into()); - self - } -} - -#[derive(Debug, Default, Serialize)] -pub struct ActivityParty { - #[serde(skip_serializing_if = "Option::is_none")] - pub id: Option, - - #[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, - - #[serde(skip_serializing_if = "Option::is_none")] - pub spectate: Option, - - // NOTE: think of a better name for this - #[serde(skip_serializing_if = "Option::is_none")] - #[serde(rename = "match")] - pub shoubu: Option, -} - -impl ActivitySecrets { - pub fn join(mut self, secret: S) -> Self - where S: Into - { - self.join = Some(secret.into()); - self - } - - pub fn spectate(mut self, secret: S) -> Self - where S: Into - { - self.spectate = Some(secret.into()); - self - } - - pub fn game(mut self, secret: S) -> Self - where S: Into - { - self.shoubu = Some(secret.into()); - self - } -} +message_format![SetActivitySecrets + join: String, + spectate: String, + game: String alias = "match", +];