1*b7893ccfSSadaf Ebrahimi /* Copyright (c) 2019 The Khronos Group Inc.
2*b7893ccfSSadaf Ebrahimi * Copyright (c) 2019 Valve Corporation
3*b7893ccfSSadaf Ebrahimi * Copyright (c) 2019 LunarG, Inc.
4*b7893ccfSSadaf Ebrahimi *
5*b7893ccfSSadaf Ebrahimi * Licensed under the Apache License, Version 2.0 (the "License");
6*b7893ccfSSadaf Ebrahimi * you may not use this file except in compliance with the License.
7*b7893ccfSSadaf Ebrahimi * You may obtain a copy of the License at
8*b7893ccfSSadaf Ebrahimi *
9*b7893ccfSSadaf Ebrahimi * http://www.apache.org/licenses/LICENSE-2.0
10*b7893ccfSSadaf Ebrahimi *
11*b7893ccfSSadaf Ebrahimi * Unless required by applicable law or agreed to in writing, software
12*b7893ccfSSadaf Ebrahimi * distributed under the License is distributed on an "AS IS" BASIS,
13*b7893ccfSSadaf Ebrahimi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*b7893ccfSSadaf Ebrahimi * See the License for the specific language governing permissions and
15*b7893ccfSSadaf Ebrahimi * limitations under the License.
16*b7893ccfSSadaf Ebrahimi *
17*b7893ccfSSadaf Ebrahimi * Author: John Zulauf <[email protected]>
18*b7893ccfSSadaf Ebrahimi *
19*b7893ccfSSadaf Ebrahimi */
20*b7893ccfSSadaf Ebrahimi #pragma once
21*b7893ccfSSadaf Ebrahimi #ifndef CAST_UTILS_H_
22*b7893ccfSSadaf Ebrahimi #define CAST_UTILS_H_
23*b7893ccfSSadaf Ebrahimi
24*b7893ccfSSadaf Ebrahimi #include <cassert>
25*b7893ccfSSadaf Ebrahimi #include <cstddef>
26*b7893ccfSSadaf Ebrahimi #include <cstdint>
27*b7893ccfSSadaf Ebrahimi #include <functional>
28*b7893ccfSSadaf Ebrahimi
29*b7893ccfSSadaf Ebrahimi #define CAST_TO_FROM_UTILS
30*b7893ccfSSadaf Ebrahimi // Casts to allow various types of less than 64 bits to be cast to and from uint64_t safely and portably
31*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename Uint>
CastFromUint(Uint untyped_handle)32*b7893ccfSSadaf Ebrahimi static inline HandleType CastFromUint(Uint untyped_handle) {
33*b7893ccfSSadaf Ebrahimi static_assert(sizeof(HandleType) == sizeof(Uint), "HandleType must be the same size as untyped handle");
34*b7893ccfSSadaf Ebrahimi return *reinterpret_cast<HandleType *>(&untyped_handle);
35*b7893ccfSSadaf Ebrahimi }
36*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename Uint>
CastToUint(HandleType handle)37*b7893ccfSSadaf Ebrahimi static inline Uint CastToUint(HandleType handle) {
38*b7893ccfSSadaf Ebrahimi static_assert(sizeof(HandleType) == sizeof(Uint), "HandleType must be the same size as untyped handle");
39*b7893ccfSSadaf Ebrahimi return *reinterpret_cast<Uint *>(&handle);
40*b7893ccfSSadaf Ebrahimi }
41*b7893ccfSSadaf Ebrahimi
42*b7893ccfSSadaf Ebrahimi // Ensure that the size changing casts are *static* to ensure portability
43*b7893ccfSSadaf Ebrahimi template <typename HandleType>
CastFromUint64(uint64_t untyped_handle)44*b7893ccfSSadaf Ebrahimi static inline HandleType CastFromUint64(uint64_t untyped_handle) {
45*b7893ccfSSadaf Ebrahimi static_assert(sizeof(HandleType) <= sizeof(uint64_t), "HandleType must be not larger than the untyped handle size");
46*b7893ccfSSadaf Ebrahimi typedef
47*b7893ccfSSadaf Ebrahimi typename std::conditional<sizeof(HandleType) == sizeof(uint8_t), uint8_t,
48*b7893ccfSSadaf Ebrahimi typename std::conditional<sizeof(HandleType) == sizeof(uint16_t), uint16_t,
49*b7893ccfSSadaf Ebrahimi typename std::conditional<sizeof(HandleType) == sizeof(uint32_t),
50*b7893ccfSSadaf Ebrahimi uint32_t, uint64_t>::type>::type>::type Uint;
51*b7893ccfSSadaf Ebrahimi return CastFromUint<HandleType, Uint>(static_cast<Uint>(untyped_handle));
52*b7893ccfSSadaf Ebrahimi }
53*b7893ccfSSadaf Ebrahimi
54*b7893ccfSSadaf Ebrahimi template <typename HandleType>
CastToUint64(HandleType handle)55*b7893ccfSSadaf Ebrahimi static uint64_t CastToUint64(HandleType handle) {
56*b7893ccfSSadaf Ebrahimi static_assert(sizeof(HandleType) <= sizeof(uint64_t), "HandleType must be not larger than the untyped handle size");
57*b7893ccfSSadaf Ebrahimi typedef
58*b7893ccfSSadaf Ebrahimi typename std::conditional<sizeof(HandleType) == sizeof(uint8_t), uint8_t,
59*b7893ccfSSadaf Ebrahimi typename std::conditional<sizeof(HandleType) == sizeof(uint16_t), uint16_t,
60*b7893ccfSSadaf Ebrahimi typename std::conditional<sizeof(HandleType) == sizeof(uint32_t),
61*b7893ccfSSadaf Ebrahimi uint32_t, uint64_t>::type>::type>::type Uint;
62*b7893ccfSSadaf Ebrahimi return static_cast<uint64_t>(CastToUint<HandleType, Uint>(handle));
63*b7893ccfSSadaf Ebrahimi }
64*b7893ccfSSadaf Ebrahimi
65*b7893ccfSSadaf Ebrahimi // Convenience functions to case between handles and the types the handles abstract, reflecting the Vulkan handle scheme, where
66*b7893ccfSSadaf Ebrahimi // Handles are either pointers (dispatchable) or sizeof(uint64_t) (non-dispatchable), s.t. full size-safe casts are used and
67*b7893ccfSSadaf Ebrahimi // we ensure that handles are large enough to contain the underlying type.
68*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename ValueType>
CastToHandle(ValueType value,HandleType * handle)69*b7893ccfSSadaf Ebrahimi void CastToHandle(ValueType value, HandleType *handle) {
70*b7893ccfSSadaf Ebrahimi static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value");
71*b7893ccfSSadaf Ebrahimi *handle = CastFromUint64<HandleType>(CastToUint64<ValueType>(value));
72*b7893ccfSSadaf Ebrahimi }
73*b7893ccfSSadaf Ebrahimi // This form is conveniently "inline", you should only need to specify the handle type (the value type being deducible from the arg)
74*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename ValueType>
CastToHandle(ValueType value)75*b7893ccfSSadaf Ebrahimi HandleType CastToHandle(ValueType value) {
76*b7893ccfSSadaf Ebrahimi HandleType handle;
77*b7893ccfSSadaf Ebrahimi CastToHandle(value, &handle);
78*b7893ccfSSadaf Ebrahimi return handle;
79*b7893ccfSSadaf Ebrahimi }
80*b7893ccfSSadaf Ebrahimi
81*b7893ccfSSadaf Ebrahimi template <typename ValueType, typename HandleType>
CastFromHandle(HandleType handle,ValueType * value)82*b7893ccfSSadaf Ebrahimi void CastFromHandle(HandleType handle, ValueType *value) {
83*b7893ccfSSadaf Ebrahimi static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value");
84*b7893ccfSSadaf Ebrahimi *value = CastFromUint64<ValueType>(CastToUint64<HandleType>(handle));
85*b7893ccfSSadaf Ebrahimi }
86*b7893ccfSSadaf Ebrahimi template <typename ValueType, typename HandleType>
CastFromHandle(HandleType handle)87*b7893ccfSSadaf Ebrahimi ValueType CastFromHandle(HandleType handle) {
88*b7893ccfSSadaf Ebrahimi ValueType value;
89*b7893ccfSSadaf Ebrahimi CastFromHandle(handle, &value);
90*b7893ccfSSadaf Ebrahimi return value;
91*b7893ccfSSadaf Ebrahimi }
92*b7893ccfSSadaf Ebrahimi
93*b7893ccfSSadaf Ebrahimi #endif // CAST_UTILS_H_
94