Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce boilerplate code with macros #61

Merged
merged 19 commits into from
Jan 30, 2022
Merged

Reduce boilerplate code with macros #61

merged 19 commits into from
Jan 30, 2022

Conversation

bewee
Copy link
Member

@bewee bewee commented Dec 29, 2021

This suggests splitting xxx_handle_mut() functions into separate traits, and adding functions xxx_handle() to these which return an immutable references. A proc macro can then be used to auto-implement these traits, including adding a field holding the handle to the struct.
Ultimately, this should also unify the code by wrapping EventHandles in Events, and adding an APIHandlerHandle. Solely the Action would remain different (would they?).

Examples

#[adapter]
struct ExampleAdapter { foo: i32 }
impl AdapterStructure for ExampleAdapter {
    fn id(&self) -> String {
        "example-adapter".to_owned()
    }
    fn name(&self) -> String {
        "Example Adapter".to_owned()
    }
}
#[async_trait]
impl Adapter for BuiltExampleAdapter {
    async fn on_remove_device(&mut self, device_id: String) -> Result<(), String> {
        log::debug!("Device {} for {} removed", device_id, self.foo);
        Ok(())
    }
}

is equivalent to

struct ExampleAdapter { foo: i32 }
impl AdapterStructure for ExampleAdapter {
    fn id(&self) -> String {
        "example-adapter".to_owned()
    }
    fn name(&self) -> String {
        "Example Adapter".to_owned()
    }
}
impl AdapterBuilder for ExampleAdapter {
    type BuiltAdapter = BuiltExampleAdapter;
    fn build(data: Self, adapter_handle: AdapterHandle) -> Self::BuiltAdapter {
        BuiltExampleAdapter { data, adapter_handle }
    }
}
struct BuiltExampleAdapter {
    data: ExampleAdapter,
    adapter_handle: AdapterHandle
}
impl BuiltAdapter for BuiltExampleAdapter {
    fn adapter_handle(&self) -> &AdapterHandle {
        &self.adapter_handle
    }
    fn adapter_handle_mut(&mut self) -> &mut AdapterHandle {
        &mut self.adapter_handle
    }
}
impl std::ops::Deref for ExampleAdapter{
    type Target = AdapterHandle;
    fn deref(&self) -> &Self::Target {
        &self.adapter_handle
    }
}
impl std::ops::DerefMut for ExampleAdapter {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.adapter_handle
    }
}
#[async_trait]
impl Adapter for BuiltExampleAdapter {
    async fn on_remove_device(&mut self, device_id: String) -> Result<(), String> {
        log::debug!("Device {} for {} removed", device_id, self.foo);
        Ok(())
    }
}

and is equivalent to previously doing

struct ExampleAdapter{
    adapter_handle: AdapterHandle,
    foo: i32,
}
impl ExampleAdapter {
    fn id() -> String {
        "example-adapter".to_owned()
    }
    fn name() -> String {
        "Example Adapter".to_owned()
    }
}
#[async_trait]
impl Adapter for ExampleAdapter {
    fn adapter_handle_mut(&mut self) -> &mut AdapterHandle {
        &mut self.adapter_handle
    }
    async fn on_remove_device(&mut self, device_id: String) -> Result<(), String> {
        log::debug!("Device {} for {} removed", device_id, self.foo);
        Ok(())
    }
}

@bewee
Copy link
Member Author

bewee commented Dec 29, 2021

Currently, property handles have to be exposed to the user during building. However, I may have an idea to solve this too 🤔

Copy link
Member

@tim-hellhake tim-hellhake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will save a lot of typing 😬

@bewee
Copy link
Member Author

bewee commented Jan 6, 2022

PR description updated

@bewee
Copy link
Member Author

bewee commented Jan 6, 2022

When rust-lang/rust#29635 was stabilized, we wouldn't even need the proc macro for this, but could simply provide a generic wrapper struct Built<T> and then implement trait Adapter on this.

@bewee bewee marked this pull request as ready for review January 6, 2022 19:15
Copy link
Member

@tim-hellhake tim-hellhake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

@tim-hellhake tim-hellhake changed the title Proc Macros Reduce boilerplate code with macros Jan 30, 2022
@tim-hellhake tim-hellhake merged commit d408809 into master Jan 30, 2022
@tim-hellhake tim-hellhake deleted the proc-macro branch January 30, 2022 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants