Skip to main content

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 crate::runtime::{
26    executor::Executor,
27    {IStatelessServiceFactory, IStatelessServiceInstance},
28};
29
30#[implement(IFabricStatelessServiceFactory)]
31pub struct StatelessServiceFactoryBridge<E>
32where
33    E: Executor + 'static,
34{
35    inner: Box<dyn IStatelessServiceFactory>,
36    rt: E,
37}
38
39impl<E> StatelessServiceFactoryBridge<E>
40where
41    E: Executor,
42{
43    pub fn create(
44        factory: Box<dyn IStatelessServiceFactory>,
45        rt: E,
46    ) -> StatelessServiceFactoryBridge<E> {
47        StatelessServiceFactoryBridge { inner: factory, rt }
48    }
49}
50
51impl<E> IFabricStatelessServiceFactory_Impl for StatelessServiceFactoryBridge_Impl<E>
52where
53    E: Executor,
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
96pub(crate) struct IFabricStatelessServiceInstanceBridge<E>
97where
98    E: Executor,
99{
100    inner: Arc<Box<dyn IStatelessServiceInstance>>,
101    rt: E,
102}
103
104impl<E> IFabricStatelessServiceInstanceBridge<E>
105where
106    E: Executor,
107{
108    pub fn create(
109        instance: Box<dyn IStatelessServiceInstance>,
110        rt: E,
111    ) -> IFabricStatelessServiceInstanceBridge<E> {
112        IFabricStatelessServiceInstanceBridge {
113            inner: Arc::new(instance),
114            rt,
115        }
116    }
117}
118
119impl<E> IFabricStatelessServiceInstance_Impl for IFabricStatelessServiceInstanceBridge_Impl<E>
120where
121    E: Executor,
122{
123    #[cfg_attr(
124        feature = "tracing",
125        tracing::instrument(skip_all, ret(level = "debug"), err)
126    )]
127    fn BeginOpen(
128        &self,
129        partition: windows_core::Ref<IFabricStatelessServicePartition>,
130        callback: windows_core::Ref<super::IFabricAsyncOperationCallback>,
131    ) -> crate::WinResult<super::IFabricAsyncOperationContext> {
132        let partition_cp = partition.unwrap().clone();
133        let partition_bridge = StatelessServicePartition::new(partition_cp);
134        let inner = self.inner.clone();
135        let (ctx, token) = BridgeContext::make(callback);
136        ctx.spawn(&self.rt, async move {
137            inner
138                .open(Arc::new(partition_bridge), token)
139                .await
140                .map(|s| IFabricStringResult::from(StringResult::new(s)))
141                .map_err(crate::WinError::from)
142        })
143    }
144
145    #[cfg_attr(
146        feature = "tracing",
147        tracing::instrument(skip_all, ret(level = "debug"), err)
148    )]
149    fn EndOpen(
150        &self,
151        context: windows_core::Ref<super::IFabricAsyncOperationContext>,
152    ) -> crate::WinResult<IFabricStringResult> {
153        BridgeContext::result(context)?
154    }
155
156    #[cfg_attr(
157        feature = "tracing",
158        tracing::instrument(skip_all, ret(level = "debug"), err)
159    )]
160    fn BeginClose(
161        &self,
162        callback: windows_core::Ref<super::IFabricAsyncOperationCallback>,
163    ) -> crate::WinResult<super::IFabricAsyncOperationContext> {
164        let inner = self.inner.clone();
165        let (ctx, token) = BridgeContext::make(callback);
166        ctx.spawn(&self.rt, async move {
167            inner.close(token).await.map_err(crate::WinError::from)
168        })
169    }
170
171    #[cfg_attr(
172        feature = "tracing",
173        tracing::instrument(skip_all, ret(level = "debug"), err)
174    )]
175    fn EndClose(
176        &self,
177        context: windows_core::Ref<super::IFabricAsyncOperationContext>,
178    ) -> crate::WinResult<()> {
179        BridgeContext::result(context)?
180    }
181
182    #[cfg_attr(
183        feature = "tracing",
184        tracing::instrument(skip_all, ret(level = "debug"))
185    )]
186    fn Abort(&self) {
187        self.inner.abort()
188    }
189}