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