Skip to content

Commit

Permalink
Similarly for device
Browse files Browse the repository at this point in the history
  • Loading branch information
bewee committed Dec 31, 2021
1 parent cf3fe4f commit 2e9e193
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 132 deletions.
111 changes: 98 additions & 13 deletions gateway-addon-rust-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ use std::str::FromStr;
use syn::DeriveInput;

/// Use this on a struct to generate a built adapter around it, including useful impls.
///
///
/// # Examples
/// ```
/// # use gateway_addon_rust::prelude::*;
/// # use async_trait::async_trait;
/// #[adapter]
/// struct ExampleAdapter { foo: i32 }
///
/// struct ExampleAdapter {
/// foo: i32,
/// }
///
/// #[async_trait]
/// impl Adapter for BuiltExampleAdapter {
/// async fn on_unload(&mut self) -> Result<(), String> {
Expand All @@ -26,13 +28,15 @@ use syn::DeriveInput;
/// # use gateway_addon_rust::{prelude::*, adapter::AdapterHandleWrapper};
/// # use std::ops::{Deref, DerefMut};
/// # use async_trait::async_trait;
/// struct ExampleAdapter { foo: i32 }
///
/// struct BuiltExampleAdapter{
/// struct ExampleAdapter {
/// foo: i32,
/// }
///
/// struct BuiltExampleAdapter {
/// data: ExampleAdapter,
/// adapter_handle: AdapterHandle
/// adapter_handle: AdapterHandle,
/// }
///
///
/// impl AdapterHandleWrapper for BuiltExampleAdapter {
/// fn adapter_handle(&self) -> &AdapterHandle {
/// &self.adapter_handle
Expand All @@ -41,27 +45,30 @@ use syn::DeriveInput;
/// &mut self.adapter_handle
/// }
/// }
///
///
/// impl BuildAdapter for ExampleAdapter {
/// type BuiltAdapter = BuiltExampleAdapter;
/// fn build(data: Self, adapter_handle: AdapterHandle) -> Self::BuiltAdapter {
/// BuiltExampleAdapter { data, adapter_handle }
/// BuiltExampleAdapter {
/// data,
/// adapter_handle,
/// }
/// }
/// }
///
///
/// impl Deref for BuiltExampleAdapter {
/// type Target = ExampleAdapter;
/// fn deref(&self) -> &Self::Target {
/// &self.data
/// }
/// }
///
///
/// impl DerefMut for BuiltExampleAdapter {
/// fn deref_mut(&mut self) -> &mut Self::Target {
/// &mut self.data
/// }
/// }
///
///
/// #[async_trait]
/// impl Adapter for BuiltExampleAdapter {
/// // ...
Expand All @@ -72,6 +79,84 @@ pub fn adapter(_args: TokenStream, input: TokenStream) -> TokenStream {
apply_macro(input, "adapter", "Adapter")
}

/// Use this on a struct to generate a built device around it, including useful impls.
///
/// # Examples
/// ```
/// # use gateway_addon_rust::prelude::*;
/// # use async_trait::async_trait;
/// #[device]
/// struct ExamplDevice {
/// foo: i32,
/// }
///
/// impl DeviceStructure for ExampleDevice {
/// // ...
/// # fn id(&self) -> String {
/// # "example-device".to_owned()
/// # }
/// # fn description(&self) -> DeviceDescription {
/// # DeviceDescription::default()
/// # }
/// }
///
/// #[async_trait]
/// impl Device for BuiltExampleDevice {}
/// ```
/// will expand to
/// ```
/// # use gateway_addon_rust::{prelude::*, device::DeviceHandleWrapper};
/// # use std::ops::{Deref, DerefMut};
/// # use async_trait::async_trait;
/// struct ExampleDevice { foo: i32 }
///
/// struct BuiltExampleDevice{
/// data: ExampleDevice,,
/// device_handle: DeviceHandle
/// }
///
/// impl DeviceHandleWrapper for BuiltExampleDevice {
/// fn device_handle(&self) -> &DeviceHandle {
/// &self.device_handle
/// }
/// fn device_handle_mut(&mut self) -> &mut DeviceHandle {
/// &mut self.device_handle
/// }
/// }
///
/// impl BuildDevice for ExampleDevice {
/// type BuiltDevice = BuiltExampleDevice;
/// fn build(data: Self, device_handle: DeviceHandle) -> Self::BuiltDevice {
/// BuiltExampleDevice { data, device_handle }
/// }
/// }
///
/// impl Deref for BuiltExampleDevice {
/// type Target = ExampleDevice;
/// fn deref(&self) -> &Self::Target {
/// &self.data
/// }
/// }
///
/// impl DerefMut for BuiltExampleDevice {
/// fn deref_mut(&mut self) -> &mut Self::Target {
/// &mut self.data
/// }
/// }
///
/// impl DeviceStructure for ExampleDevice {
/// // ...
/// # fn id(&self) -> String {
/// # "example-device".to_owned()
/// # }
/// # fn description(&self) -> DeviceDescription {
/// # DeviceDescription::default()
/// # }
/// }
///
/// #[async_trait]
/// impl Device for BuiltExampleDevice {}
/// ```
#[proc_macro_attribute]
pub fn device(_args: TokenStream, input: TokenStream) -> TokenStream {
apply_macro(input, "device", "Device")
Expand Down
43 changes: 23 additions & 20 deletions src/adapter/adapter_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.*
*/

use crate::{client::Client, error::WebthingsError, Adapter, Device, DeviceBuilder, DeviceHandle};
use crate::{
client::Client,
device::{BuildDevice, DeviceStructure},
error::WebthingsError,
Adapter, Device, DeviceHandle,
};
use std::{
collections::HashMap,
sync::{Arc, Weak},
Expand Down Expand Up @@ -38,16 +43,12 @@ impl AdapterHandle {
}
}

/// Build and add a new device using the given [device builder][crate::DeviceBuilder].
pub async fn add_device<D, B>(
/// Build and add a new device using the given data struct.
pub async fn add_device<D: BuildDevice + DeviceStructure>(
&mut self,
device_builder: B,
) -> Result<Arc<Mutex<Box<dyn Device>>>, WebthingsError>
where
D: Device,
B: DeviceBuilder<Device = D>,
{
let device_description = device_builder.full_description()?;
device: D,
) -> Result<Arc<Mutex<Box<dyn Device>>>, WebthingsError> {
let device_description = device.full_description()?;

let message: Message = DeviceAddedNotificationMessageData {
plugin_id: self.plugin_id.clone(),
Expand All @@ -65,16 +66,16 @@ impl AdapterHandle {
self.weak.clone(),
self.plugin_id.clone(),
self.adapter_id.clone(),
device_builder.id(),
device_builder.description(),
device.id(),
device.description(),
);

let properties = device_builder.properties();
let actions = device_builder.actions();
let events = device_builder.events();
let properties = device.properties();
let actions = device.actions();
let events = device.events();

let device: Arc<Mutex<Box<dyn Device>>> =
Arc::new(Mutex::new(Box::new(device_builder.build(device_handle))));
Arc::new(Mutex::new(Box::new(D::build(device, device_handle))));
let device_weak = Arc::downgrade(&device);

{
Expand Down Expand Up @@ -145,7 +146,9 @@ impl AdapterHandle {
#[cfg(test)]
pub(crate) mod tests {
use crate::{
client::Client, device::tests::MockDeviceBuilder, AdapterHandle, Device, DeviceBuilder,
client::Client,
device::{tests::MockDevice, DeviceStructure},
AdapterHandle, Device,
};
use rstest::{fixture, rstest};
use std::sync::Arc;
Expand All @@ -156,8 +159,8 @@ pub(crate) mod tests {
adapter: &mut AdapterHandle,
device_id: &str,
) -> Arc<Mutex<Box<dyn Device>>> {
let device_builder = MockDeviceBuilder::new(device_id.to_owned());
let expected_description = device_builder.full_description().unwrap();
let device = MockDevice::new(device_id.to_owned());
let expected_description = device.full_description().unwrap();

let plugin_id = adapter.plugin_id.to_owned();
let adapter_id = adapter.adapter_id.to_owned();
Expand All @@ -178,7 +181,7 @@ pub(crate) mod tests {
.times(1)
.returning(|_| Ok(()));

adapter.add_device(device_builder).await.unwrap()
adapter.add_device(device).await.unwrap()
}

const PLUGIN_ID: &str = "plugin_id";
Expand Down
8 changes: 4 additions & 4 deletions src/adapter/adapter_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use webthings_gateway_ipc_types::DeviceWithoutId;
///
/// # Examples
/// ```no_run
/// # use gateway_addon_rust::{prelude::*, plugin::connect, example::ExampleDeviceBuilder, error::WebthingsError, adapter::AdapterHandleWrapper};
/// # use gateway_addon_rust::{prelude::*, plugin::connect, example::ExampleDevice, error::WebthingsError, adapter::AdapterHandleWrapper};
/// # use webthings_gateway_ipc_types::DeviceWithoutId;
/// # use async_trait::async_trait;
/// # use as_any::Downcast;
Expand All @@ -41,7 +41,7 @@ use webthings_gateway_ipc_types::DeviceWithoutId;
/// impl BuiltExampleAdapter {
/// pub async fn init(&mut self) -> Result<(), WebthingsError> {
/// self.adapter_handle_mut()
/// .add_device(ExampleDeviceBuilder::new())
/// .add_device(ExampleDevice::new())
/// .await?;
/// Ok(())
/// }
Expand Down Expand Up @@ -107,7 +107,7 @@ pub trait Adapter: AdapterHandleWrapper + Send + Sync + AsAny + 'static {
impl Downcast for dyn Adapter {}

/// A trait used to wrap an [adapter handle][AdapterHandle].
///
///
/// When you use the [adapter][macro@crate::adapter] macro, this will be implemented automatically.
///
/// # Examples
Expand Down Expand Up @@ -178,7 +178,7 @@ pub trait AdapterHandleWrapper {
pub trait BuildAdapter {
/// Type of [Adapter] to build.
type BuiltAdapter: Adapter;

/// Build the [adapter][Adapter] from a data struct and an [adapter handle][AdapterHandle].
fn build(data: Self, adapter_handle: AdapterHandle) -> Self::BuiltAdapter;
}
Expand Down
2 changes: 1 addition & 1 deletion src/api_handler/api_handler_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use async_trait::async_trait;
/// # Examples
/// ```no_run
/// # use gateway_addon_rust::{
/// # prelude::*, plugin::connect, example::ExampleDeviceBuilder,
/// # prelude::*, plugin::connect,
/// # api_handler::{ApiHandler, ApiRequest, ApiResponse}, error::WebthingsError
/// # };
/// # use async_trait::async_trait;
Expand Down
2 changes: 1 addition & 1 deletion src/device/device_description.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use webthings_gateway_ipc_types::{

/// A struct which represents a WoT [device description][webthings_gateway_ipc_types::Device].
///
/// This is used by [DeviceBuilder][crate::DeviceBuilder].
/// This is used by [DeviceStructure][crate::DeviceStructure].
///
/// Use the provided builder methods instead of directly writing to the struct fields.
///
Expand Down
Loading

0 comments on commit 2e9e193

Please sign in to comment.