mssf_core/runtime/
stateless_bridge.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
6// windows::core::implement macro generates snake case types.
7#![allow(non_camel_case_types)]
8
9use std::sync::Arc;
10
11use crate::{runtime::StatelessServicePartition, strings::WStringWrap, sync::BridgeContext};
12use mssf_com::{
13    FabricCommon::IFabricStringResult,
14    FabricRuntime::{
15        IFabricStatelessServiceFactory, IFabricStatelessServiceFactory_Impl,
16        IFabricStatelessServiceInstance, IFabricStatelessServiceInstance_Impl,
17        IFabricStatelessServicePartition,
18    },
19    FabricTypes::FABRIC_URI,
20};
21use windows_core::implement;
22
23use super::{
24    executor::Executor,
25    stateless::{StatelessServiceFactory, StatelessServiceInstance},
26};
27
28#[implement(IFabricStatelessServiceFactory)]
29pub struct StatelessServiceFactoryBridge<E, F>
30where
31    E: Executor + 'static,
32    F: StatelessServiceFactory + 'static,
33{
34    inner: F,
35    rt: E,
36}
37
38impl<E, F> StatelessServiceFactoryBridge<E, F>
39where
40    E: Executor,
41    F: StatelessServiceFactory,
42{
43    pub fn create(factory: F, rt: E) -> StatelessServiceFactoryBridge<E, F> {
44        StatelessServiceFactoryBridge::<E, F> { inner: factory, rt }
45    }
46}
47
48impl<E, F> IFabricStatelessServiceFactory_Impl for StatelessServiceFactoryBridge_Impl<E, F>
49where
50    E: Executor,
51    F: StatelessServiceFactory,
52{
53    #[allow(clippy::not_unsafe_ptr_arg_deref)]
54    #[cfg_attr(
55        feature = "tracing",
56        tracing::instrument(skip_all, ret(level = "debug"), err)
57    )]
58    fn CreateInstance(
59        &self,
60        servicetypename: &crate::PCWSTR,
61        servicename: FABRIC_URI,
62        initializationdatalength: u32,
63        initializationdata: *const u8,
64        partitionid: &crate::GUID,
65        instanceid: i64,
66    ) -> crate::WinResult<IFabricStatelessServiceInstance> {
67        let h_servicename = WStringWrap::from(crate::PCWSTR(servicename.0)).into();
68        let h_servicetypename = WStringWrap::from(*servicetypename).into();
69        let data = unsafe {
70            if !initializationdata.is_null() {
71                std::slice::from_raw_parts(initializationdata, initializationdatalength as usize)
72            } else {
73                &[]
74            }
75        };
76
77        let instance = self.inner.create_instance(
78            &h_servicetypename,
79            &h_servicename,
80            data,
81            partitionid,
82            instanceid,
83        )?;
84        let rt = self.rt.clone();
85        let instance_bridge = IFabricStatelessServiceInstanceBridge::create(instance, rt);
86
87        Ok(instance_bridge.into())
88    }
89}
90
91// bridge from safe service instance to com
92#[implement(IFabricStatelessServiceInstance)]
93
94struct IFabricStatelessServiceInstanceBridge<E, S>
95where
96    E: Executor,
97    S: StatelessServiceInstance + 'static,
98{
99    inner: Arc<S>,
100    rt: E,
101}
102
103impl<E, S> IFabricStatelessServiceInstanceBridge<E, S>
104where
105    E: Executor,
106    S: StatelessServiceInstance,
107{
108    pub fn create(instance: S, rt: E) -> IFabricStatelessServiceInstanceBridge<E, S>
109    where
110        S: StatelessServiceInstance,
111    {
112        IFabricStatelessServiceInstanceBridge {
113            inner: Arc::new(instance),
114            rt,
115        }
116    }
117}
118
119impl<E, S> IFabricStatelessServiceInstance_Impl for IFabricStatelessServiceInstanceBridge_Impl<E, S>
120where
121    E: Executor,
122    S: StatelessServiceInstance + 'static,
123{
124    #[cfg_attr(
125        feature = "tracing",
126        tracing::instrument(skip_all, ret(level = "debug"), err)
127    )]
128    fn BeginOpen(
129        &self,
130        partition: windows_core::Ref<IFabricStatelessServicePartition>,
131        callback: windows_core::Ref<super::IFabricAsyncOperationCallback>,
132    ) -> crate::WinResult<super::IFabricAsyncOperationContext> {
133        let partition_cp = partition.unwrap().clone();
134        let partition_bridge = StatelessServicePartition::new(partition_cp);
135        let inner = self.inner.clone();
136        let (ctx, token) = BridgeContext::make(callback);
137        ctx.spawn(&self.rt, async move {
138            inner
139                .open(&partition_bridge, token)
140                .await
141                .map(|s| IFabricStringResult::from(WStringWrap::from(s)))
142                .map_err(crate::WinError::from)
143        })
144    }
145
146    #[cfg_attr(
147        feature = "tracing",
148        tracing::instrument(skip_all, ret(level = "debug"), err)
149    )]
150    fn EndOpen(
151        &self,
152        context: windows_core::Ref<super::IFabricAsyncOperationContext>,
153    ) -> crate::WinResult<IFabricStringResult> {
154        BridgeContext::result(context)?
155    }
156
157    #[cfg_attr(
158        feature = "tracing",
159        tracing::instrument(skip_all, ret(level = "debug"), err)
160    )]
161    fn BeginClose(
162        &self,
163        callback: windows_core::Ref<super::IFabricAsyncOperationCallback>,
164    ) -> crate::WinResult<super::IFabricAsyncOperationContext> {
165        let inner = self.inner.clone();
166        let (ctx, token) = BridgeContext::make(callback);
167        ctx.spawn(&self.rt, async move {
168            inner.close(token).await.map_err(crate::WinError::from)
169        })
170    }
171
172    #[cfg_attr(
173        feature = "tracing",
174        tracing::instrument(skip_all, ret(level = "debug"), err)
175    )]
176    fn EndClose(
177        &self,
178        context: windows_core::Ref<super::IFabricAsyncOperationContext>,
179    ) -> crate::WinResult<()> {
180        BridgeContext::result(context)?
181    }
182
183    #[cfg_attr(
184        feature = "tracing",
185        tracing::instrument(skip_all, ret(level = "debug"))
186    )]
187    fn Abort(&self) {
188        self.inner.abort()
189    }
190}