xref: /aosp_15_r20/external/cronet/base/win/winrt_foundation_helpers.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <windows.foundation.h>
9*6777b538SAndroid Build Coastguard Worker #include <wrl/client.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <algorithm>
12*6777b538SAndroid Build Coastguard Worker #include <optional>
13*6777b538SAndroid Build Coastguard Worker #include <vector>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker // This file provides helpers for WinRT types.
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace base::win::internal {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker // Template tricks needed to dispatch to the correct implementation.
22*6777b538SAndroid Build Coastguard Worker //
23*6777b538SAndroid Build Coastguard Worker // For all types which are neither InterfaceGroups nor RuntimeClasses, the
24*6777b538SAndroid Build Coastguard Worker // following three typedefs are synonyms for a single C++ type.  But for
25*6777b538SAndroid Build Coastguard Worker // InterfaceGroups and RuntimeClasses, they are different types:
26*6777b538SAndroid Build Coastguard Worker //   LogicalT: The C++ Type for the InterfaceGroup or RuntimeClass, when
27*6777b538SAndroid Build Coastguard Worker //             used as a template parameter.  Eg "RCFoo*"
28*6777b538SAndroid Build Coastguard Worker //   AbiT:     The C++ type for the default interface used to represent the
29*6777b538SAndroid Build Coastguard Worker //             InterfaceGroup or RuntimeClass when passed as a method parameter.
30*6777b538SAndroid Build Coastguard Worker //             Eg "IFoo*"
31*6777b538SAndroid Build Coastguard Worker //   ComplexT: An instantiation of the Internal "AggregateType" template that
32*6777b538SAndroid Build Coastguard Worker //             combines LogicalT with AbiT. Eg "AggregateType<RCFoo*,IFoo*>".
33*6777b538SAndroid Build Coastguard Worker //             ComplexT is tightly coupled to the interface being implemented,
34*6777b538SAndroid Build Coastguard Worker //             hence defined in headers which include this file.
35*6777b538SAndroid Build Coastguard Worker //             For instance base/win/async_operation.h or
36*6777b538SAndroid Build Coastguard Worker //             base/win/collection_helpers.h
37*6777b538SAndroid Build Coastguard Worker //
38*6777b538SAndroid Build Coastguard Worker // windows.foundation.collections.h defines the following template and
39*6777b538SAndroid Build Coastguard Worker // semantics in Windows::Foundation::Internal:
40*6777b538SAndroid Build Coastguard Worker //
41*6777b538SAndroid Build Coastguard Worker // template <class LogicalType, class AbiType>
42*6777b538SAndroid Build Coastguard Worker // struct AggregateType;
43*6777b538SAndroid Build Coastguard Worker //
44*6777b538SAndroid Build Coastguard Worker //   LogicalType - the Windows Runtime type (eg, runtime class, interface group,
45*6777b538SAndroid Build Coastguard Worker //                 etc) being provided as an argument to an _impl template, when
46*6777b538SAndroid Build Coastguard Worker //                 that type cannot be represented at the ABI.
47*6777b538SAndroid Build Coastguard Worker //   AbiType     - the type used for marshalling, ie "at the ABI", for the
48*6777b538SAndroid Build Coastguard Worker //                 logical type.
49*6777b538SAndroid Build Coastguard Worker template <typename TComplex>
50*6777b538SAndroid Build Coastguard Worker using AbiType =
51*6777b538SAndroid Build Coastguard Worker     typename ABI::Windows::Foundation::Internal::GetAbiType<TComplex>::type;
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker template <typename TComplex>
54*6777b538SAndroid Build Coastguard Worker using LogicalType =
55*6777b538SAndroid Build Coastguard Worker     typename ABI::Windows::Foundation::Internal::GetLogicalType<TComplex>::type;
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker // Compile time switch to decide what container to use for |TComplex|.
58*6777b538SAndroid Build Coastguard Worker // Depends on whether the underlying Abi type is a pointer to IUnknown or not.
59*6777b538SAndroid Build Coastguard Worker // It queries the internals of Windows::Foundation to obtain this information.
60*6777b538SAndroid Build Coastguard Worker template <typename TComplex>
61*6777b538SAndroid Build Coastguard Worker using StorageType = std::conditional_t<
62*6777b538SAndroid Build Coastguard Worker     std::is_convertible_v<AbiType<TComplex>, IUnknown*>,
63*6777b538SAndroid Build Coastguard Worker     Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>,
64*6777b538SAndroid Build Coastguard Worker     AbiType<TComplex>>;
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker // Similar to StorageType, but returns a std::optional in case underlying Abi
67*6777b538SAndroid Build Coastguard Worker // type is not a pointer to IUnknown.
68*6777b538SAndroid Build Coastguard Worker template <typename TComplex>
69*6777b538SAndroid Build Coastguard Worker using OptionalStorageType = std::conditional_t<
70*6777b538SAndroid Build Coastguard Worker     std::is_convertible_v<AbiType<TComplex>, IUnknown*>,
71*6777b538SAndroid Build Coastguard Worker     Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiType<TComplex>>>,
72*6777b538SAndroid Build Coastguard Worker     std::optional<AbiType<TComplex>>>;
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker template <typename T>
CopyTo(const T & value,T * ptr)75*6777b538SAndroid Build Coastguard Worker HRESULT CopyTo(const T& value, T* ptr) {
76*6777b538SAndroid Build Coastguard Worker   *ptr = value;
77*6777b538SAndroid Build Coastguard Worker   return S_OK;
78*6777b538SAndroid Build Coastguard Worker }
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker template <typename T>
CopyTo(const Microsoft::WRL::ComPtr<T> & value,T ** ptr)81*6777b538SAndroid Build Coastguard Worker HRESULT CopyTo(const Microsoft::WRL::ComPtr<T>& value, T** ptr) {
82*6777b538SAndroid Build Coastguard Worker   return value.CopyTo(ptr);
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker template <typename T>
CopyTo(const std::optional<T> & value,T * ptr)86*6777b538SAndroid Build Coastguard Worker HRESULT CopyTo(const std::optional<T>& value, T* ptr) {
87*6777b538SAndroid Build Coastguard Worker   *ptr = *value;
88*6777b538SAndroid Build Coastguard Worker   return S_OK;
89*6777b538SAndroid Build Coastguard Worker }
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker template <typename T>
CopyN(typename std::vector<T>::const_iterator first,unsigned count,T * result)92*6777b538SAndroid Build Coastguard Worker HRESULT CopyN(typename std::vector<T>::const_iterator first,
93*6777b538SAndroid Build Coastguard Worker               unsigned count,
94*6777b538SAndroid Build Coastguard Worker               T* result) {
95*6777b538SAndroid Build Coastguard Worker   std::copy_n(first, count, result);
96*6777b538SAndroid Build Coastguard Worker   return S_OK;
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker template <typename T>
CopyN(typename std::vector<Microsoft::WRL::ComPtr<T>>::const_iterator first,unsigned count,T ** result)100*6777b538SAndroid Build Coastguard Worker HRESULT CopyN(
101*6777b538SAndroid Build Coastguard Worker     typename std::vector<Microsoft::WRL::ComPtr<T>>::const_iterator first,
102*6777b538SAndroid Build Coastguard Worker     unsigned count,
103*6777b538SAndroid Build Coastguard Worker     T** result) {
104*6777b538SAndroid Build Coastguard Worker   for (unsigned i = 0; i < count; ++i) {
105*6777b538SAndroid Build Coastguard Worker     CopyTo(*first++, result++);
106*6777b538SAndroid Build Coastguard Worker   }
107*6777b538SAndroid Build Coastguard Worker   return S_OK;
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker 
IsEqual(const HSTRING & lhs,const HSTRING & rhs)110*6777b538SAndroid Build Coastguard Worker inline bool IsEqual(const HSTRING& lhs, const HSTRING& rhs) {
111*6777b538SAndroid Build Coastguard Worker   INT32 result;
112*6777b538SAndroid Build Coastguard Worker   HRESULT hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result);
113*6777b538SAndroid Build Coastguard Worker   DCHECK(SUCCEEDED(hr));
114*6777b538SAndroid Build Coastguard Worker   return result == 0;
115*6777b538SAndroid Build Coastguard Worker }
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker template <typename T>
IsEqual(const T & lhs,const T & rhs)118*6777b538SAndroid Build Coastguard Worker bool IsEqual(const T& lhs, const T& rhs) {
119*6777b538SAndroid Build Coastguard Worker   return lhs == rhs;
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker template <typename T>
IsEqual(const Microsoft::WRL::ComPtr<T> & com_ptr,const T * ptr)123*6777b538SAndroid Build Coastguard Worker bool IsEqual(const Microsoft::WRL::ComPtr<T>& com_ptr, const T* ptr) {
124*6777b538SAndroid Build Coastguard Worker   return com_ptr.Get() == ptr;
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker 
127*6777b538SAndroid Build Coastguard Worker struct Less {
operatorLess128*6777b538SAndroid Build Coastguard Worker   bool operator()(const HSTRING& lhs, const HSTRING& rhs) const {
129*6777b538SAndroid Build Coastguard Worker     INT32 result;
130*6777b538SAndroid Build Coastguard Worker     HRESULT hr = ::WindowsCompareStringOrdinal(lhs, rhs, &result);
131*6777b538SAndroid Build Coastguard Worker     DCHECK(SUCCEEDED(hr));
132*6777b538SAndroid Build Coastguard Worker     return result < 0;
133*6777b538SAndroid Build Coastguard Worker   }
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   template <typename T>
operatorLess136*6777b538SAndroid Build Coastguard Worker   bool operator()(const Microsoft::WRL::ComPtr<T>& com_ptr,
137*6777b538SAndroid Build Coastguard Worker                   const T* ptr) const {
138*6777b538SAndroid Build Coastguard Worker     return com_ptr.Get() < ptr;
139*6777b538SAndroid Build Coastguard Worker   }
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   template <typename T>
operatorLess142*6777b538SAndroid Build Coastguard Worker   constexpr bool operator()(const T& lhs, const T& rhs) const {
143*6777b538SAndroid Build Coastguard Worker     return lhs < rhs;
144*6777b538SAndroid Build Coastguard Worker   }
145*6777b538SAndroid Build Coastguard Worker };
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker }  // namespace base::win::internal
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker #endif  // BASE_WIN_WINRT_FOUNDATION_HELPERS_H_
150