xref: /aosp_15_r20/external/cronet/base/win/variant_conversions.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_WIN_VARIANT_CONVERSIONS_H_
6 #define BASE_WIN_VARIANT_CONVERSIONS_H_
7 
8 #include <oaidl.h>
9 #include <stdint.h>
10 #include <wtypes.h>
11 
12 #include "base/check.h"
13 
14 namespace base {
15 namespace win {
16 namespace internal {
17 
18 // Returns true if a VARIANT of type |self| can be assigned to a
19 // variant of type |other|.
20 // Does not allow converting unsigned <-> signed or converting between
21 // different sized types, but does allow converting IDispatch* -> IUnknown*.
VarTypeIsConvertibleTo(VARTYPE self,VARTYPE other)22 constexpr bool VarTypeIsConvertibleTo(VARTYPE self, VARTYPE other) {
23   // IDispatch inherits from IUnknown, so it's safe to
24   // upcast a VT_DISPATCH into an IUnknown*.
25   return (self == other) || (self == VT_DISPATCH && other == VT_UNKNOWN);
26 }
27 
28 // VartypeToNativeType contains the underlying |Type| and offset to the
29 // VARIANT union member related to the |ElementVartype| for simple types.
30 template <VARTYPE ElementVartype>
31 struct VartypeToNativeType final {};
32 
33 template <>
34 struct VartypeToNativeType<VT_BOOL> final {
35   using Type = VARIANT_BOOL;
36   static constexpr VARIANT_BOOL VARIANT::*kMemberOffset = &VARIANT::boolVal;
37 };
38 
39 template <>
40 struct VartypeToNativeType<VT_I1> final {
41   using Type = int8_t;
42   static constexpr CHAR VARIANT::*kMemberOffset = &VARIANT::cVal;
43 };
44 
45 template <>
46 struct VartypeToNativeType<VT_UI1> final {
47   using Type = uint8_t;
48   static constexpr BYTE VARIANT::*kMemberOffset = &VARIANT::bVal;
49 };
50 
51 template <>
52 struct VartypeToNativeType<VT_I2> final {
53   using Type = int16_t;
54   static constexpr SHORT VARIANT::*kMemberOffset = &VARIANT::iVal;
55 };
56 
57 template <>
58 struct VartypeToNativeType<VT_UI2> final {
59   using Type = uint16_t;
60   static constexpr USHORT VARIANT::*kMemberOffset = &VARIANT::uiVal;
61 };
62 
63 template <>
64 struct VartypeToNativeType<VT_I4> final {
65   using Type = int32_t;
66   static constexpr LONG VARIANT::*kMemberOffset = &VARIANT::lVal;
67 };
68 
69 template <>
70 struct VartypeToNativeType<VT_UI4> final {
71   using Type = uint32_t;
72   static constexpr ULONG VARIANT::*kMemberOffset = &VARIANT::ulVal;
73 };
74 
75 template <>
76 struct VartypeToNativeType<VT_I8> final {
77   using Type = int64_t;
78   static constexpr LONGLONG VARIANT::*kMemberOffset = &VARIANT::llVal;
79 };
80 
81 template <>
82 struct VartypeToNativeType<VT_UI8> final {
83   using Type = uint64_t;
84   static constexpr ULONGLONG VARIANT::*kMemberOffset = &VARIANT::ullVal;
85 };
86 
87 template <>
88 struct VartypeToNativeType<VT_R4> final {
89   using Type = float;
90   static constexpr FLOAT VARIANT::*kMemberOffset = &VARIANT::fltVal;
91 };
92 
93 template <>
94 struct VartypeToNativeType<VT_R8> final {
95   using Type = double;
96   static constexpr DOUBLE VARIANT::*kMemberOffset = &VARIANT::dblVal;
97 };
98 
99 template <>
100 struct VartypeToNativeType<VT_DATE> final {
101   using Type = DATE;
102   static constexpr DATE VARIANT::*kMemberOffset = &VARIANT::date;
103 };
104 
105 template <>
106 struct VartypeToNativeType<VT_BSTR> final {
107   using Type = BSTR;
108   static constexpr BSTR VARIANT::*kMemberOffset = &VARIANT::bstrVal;
109 };
110 
111 template <>
112 struct VartypeToNativeType<VT_UNKNOWN> final {
113   using Type = IUnknown*;
114   static constexpr IUnknown* VARIANT::*kMemberOffset = &VARIANT::punkVal;
115 };
116 
117 template <>
118 struct VartypeToNativeType<VT_DISPATCH> final {
119   using Type = IDispatch*;
120   static constexpr IDispatch* VARIANT::*kMemberOffset = &VARIANT::pdispVal;
121 };
122 
123 // VariantConverter contains the underlying |Type| and helper methods
124 // related to the |ElementVartype| for simple types.
125 template <VARTYPE ElementVartype>
126 struct VariantConverter final {
127   using Type = typename VartypeToNativeType<ElementVartype>::Type;
128   static constexpr bool IsConvertibleTo(VARTYPE vartype) {
129     return VarTypeIsConvertibleTo(ElementVartype, vartype);
130   }
131   static constexpr bool IsConvertibleFrom(VARTYPE vartype) {
132     return VarTypeIsConvertibleTo(vartype, ElementVartype);
133   }
134   // Get the associated VARIANT union member value.
135   // Returns the value owned by the VARIANT without affecting the lifetime
136   // of managed contents.
137   // e.g. Does not affect IUnknown* reference counts or allocate a BSTR.
138   static Type RawGet(const VARIANT& var) {
139     DCHECK(IsConvertibleFrom(V_VT(&var)));
140     return var.*VartypeToNativeType<ElementVartype>::kMemberOffset;
141   }
142   // Set the associated VARIANT union member value.
143   // The caller is responsible for handling the lifetime of managed contents.
144   // e.g. Incrementing IUnknown* reference counts or allocating a BSTR.
145   static void RawSet(VARIANT* var, Type value) {
146     DCHECK(IsConvertibleTo(V_VT(var)));
147     var->*VartypeToNativeType<ElementVartype>::kMemberOffset = value;
148   }
149 };
150 
151 }  // namespace internal
152 }  // namespace win
153 }  // namespace base
154 
155 #endif  // BASE_WIN_VARIANT_CONVERSIONS_H_
156