/* Copyright (c) 2019 The Khronos Group Inc. * Copyright (c) 2019 Valve Corporation * Copyright (c) 2019 LunarG, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Author: John Zulauf * */ #pragma once #ifndef CAST_UTILS_H_ #define CAST_UTILS_H_ #include #include #include #include #define CAST_TO_FROM_UTILS // Casts to allow various types of less than 64 bits to be cast to and from uint64_t safely and portably template static inline HandleType CastFromUint(Uint untyped_handle) { static_assert(sizeof(HandleType) == sizeof(Uint), "HandleType must be the same size as untyped handle"); return *reinterpret_cast(&untyped_handle); } template static inline Uint CastToUint(HandleType handle) { static_assert(sizeof(HandleType) == sizeof(Uint), "HandleType must be the same size as untyped handle"); return *reinterpret_cast(&handle); } // Ensure that the size changing casts are *static* to ensure portability template static inline HandleType CastFromUint64(uint64_t untyped_handle) { static_assert(sizeof(HandleType) <= sizeof(uint64_t), "HandleType must be not larger than the untyped handle size"); typedef typename std::conditional::type>::type>::type Uint; return CastFromUint(static_cast(untyped_handle)); } template static uint64_t CastToUint64(HandleType handle) { static_assert(sizeof(HandleType) <= sizeof(uint64_t), "HandleType must be not larger than the untyped handle size"); typedef typename std::conditional::type>::type>::type Uint; return static_cast(CastToUint(handle)); } // Convenience functions to case between handles and the types the handles abstract, reflecting the Vulkan handle scheme, where // Handles are either pointers (dispatchable) or sizeof(uint64_t) (non-dispatchable), s.t. full size-safe casts are used and // we ensure that handles are large enough to contain the underlying type. template void CastToHandle(ValueType value, HandleType *handle) { static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value"); *handle = CastFromUint64(CastToUint64(value)); } // This form is conveniently "inline", you should only need to specify the handle type (the value type being deducible from the arg) template HandleType CastToHandle(ValueType value) { HandleType handle; CastToHandle(value, &handle); return handle; } template void CastFromHandle(HandleType handle, ValueType *value) { static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value"); *value = CastFromUint64(CastToUint64(handle)); } template ValueType CastFromHandle(HandleType handle) { ValueType value; CastFromHandle(handle, &value); return value; } #endif // CAST_UTILS_H_