mssf_core/client/
connection.rs

1// ------------------------------------------------------------
2// Copyright (c) Microsoft Corporation.  All rights reserved.
3// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
4// --------------------------------------------------
5
6use mssf_com::FabricClient::{
7    IFabricClientConnectionEventHandler, IFabricClientConnectionEventHandler_Impl,
8    IFabricGatewayInformationResult,
9};
10
11use crate::{strings::WStringWrap, types::NodeId};
12
13/// Internal trait that rust code implements that can be bridged into IFabricClientConnectionEventHandler.
14/// Not exposed to user.
15pub trait ClientConnectionEventHandler: 'static {
16    fn on_connected(&self, info: &GatewayInformationResult) -> crate::Result<()>;
17    fn on_disconnected(&self, info: &GatewayInformationResult) -> crate::Result<()>;
18}
19
20/// FabricClient connection information.
21/// Traslated from IFabricGatewayInformationResult
22#[derive(Debug, Clone)]
23pub struct GatewayInformationResult {
24    pub node_address: crate::WString,
25    pub node_id: NodeId,
26    pub node_instance_id: u64,
27    pub node_name: crate::WString,
28}
29
30impl From<&IFabricGatewayInformationResult> for GatewayInformationResult {
31    fn from(com: &IFabricGatewayInformationResult) -> Self {
32        let info = unsafe { com.get_GatewayInformation().as_ref().unwrap() };
33        Self {
34            node_address: WStringWrap::from(info.NodeAddress).into(),
35            node_id: info.NodeId.into(),
36            node_instance_id: info.NodeInstanceId,
37            node_name: WStringWrap::from(info.NodeName).into(),
38        }
39    }
40}
41
42/// Bridge for IFabricClientConnectionEventHandler.
43/// Turn rust trait into SF com object.
44#[windows_core::implement(IFabricClientConnectionEventHandler)]
45pub struct ClientConnectionEventHandlerBridge<T>
46where
47    T: ClientConnectionEventHandler,
48{
49    inner: T,
50}
51
52impl<T> ClientConnectionEventHandlerBridge<T>
53where
54    T: ClientConnectionEventHandler,
55{
56    pub fn new(inner: T) -> Self {
57        Self { inner }
58    }
59    pub fn new_com(inner: T) -> IFabricClientConnectionEventHandler {
60        Self::new(inner).into()
61    }
62}
63
64impl<T> IFabricClientConnectionEventHandler_Impl for ClientConnectionEventHandlerBridge_Impl<T>
65where
66    T: ClientConnectionEventHandler,
67{
68    fn OnConnected(
69        &self,
70        gw_info: windows_core::Ref<IFabricGatewayInformationResult>,
71    ) -> crate::WinResult<()> {
72        let info = GatewayInformationResult::from(gw_info.unwrap());
73        self.inner
74            .on_connected(&info)
75            .map_err(crate::WinError::from)
76    }
77
78    fn OnDisconnected(
79        &self,
80        gw_info: windows_core::Ref<IFabricGatewayInformationResult>,
81    ) -> crate::WinResult<()> {
82        let info = GatewayInformationResult::from(gw_info.unwrap());
83        self.inner
84            .on_disconnected(&info)
85            .map_err(crate::WinError::from)
86    }
87}
88
89/// Connection notification function signature to avoid code repeatition.
90/// Trait alias feature in rust (not yet stable) would eliminate this trait definition.
91pub trait ConnectionNotificationFn:
92    Fn(&GatewayInformationResult) -> crate::Result<()> + 'static
93{
94}
95impl<T: Fn(&GatewayInformationResult) -> crate::Result<()> + 'static> ConnectionNotificationFn
96    for T
97{
98}
99
100/// Lambda implementation of the ClientConnectionEventHandler trait.
101/// This is used in FabricClientBuilder to build handler from functions.
102pub struct LambdaClientConnectionNotificationHandler {
103    f_conn: Option<Box<dyn ConnectionNotificationFn>>,
104    f_disconn: Option<Box<dyn ConnectionNotificationFn>>,
105}
106
107impl LambdaClientConnectionNotificationHandler {
108    pub fn new() -> Self {
109        Self {
110            f_conn: None,
111            f_disconn: None,
112        }
113    }
114
115    /// Set the on_connected callback.
116    pub fn set_f_conn(&mut self, f: impl ConnectionNotificationFn) {
117        self.f_conn = Some(Box::new(f));
118    }
119
120    /// Set the on_disconnected callback.
121    pub fn set_f_disconn(&mut self, f: impl ConnectionNotificationFn) {
122        self.f_disconn = Some(Box::new(f));
123    }
124}
125
126impl ClientConnectionEventHandler for LambdaClientConnectionNotificationHandler {
127    fn on_connected(&self, info: &GatewayInformationResult) -> crate::Result<()> {
128        if let Some(f) = &self.f_conn {
129            f(info)
130        } else {
131            Ok(())
132        }
133    }
134
135    fn on_disconnected(&self, info: &GatewayInformationResult) -> crate::Result<()> {
136        if let Some(f) = &self.f_disconn {
137            f(info)
138        } else {
139            Ok(())
140        }
141    }
142}