/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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. */ #pragma once #include #include #include #include namespace apache { namespace thrift { namespace op { namespace detail { using FieldId = type::FieldId; using Ptr = type::detail::Ptr; using Dyn = type::detail::Dyn; using RuntimeType = type::detail::RuntimeType; using TypeInfo = type::detail::TypeInfo; using IterType = type::detail::IterType; template const TypeInfo& getAnyTypeInfo(); // Create a AnyOp-based Thrift runtime type. template > RuntimeType getAnyType() { static_assert( std::is_same, type::native_type>::value, "type missmatch"); return RuntimeType::create(getAnyTypeInfo()); } // Compile-time and type-erased Thrift operator implementations. template struct AnyOp; // Ops all Thrift types support. template struct BaseOp : type::detail::BaseErasedOp { // Blind convert the pointer to the native type. using T = type::native_type; static T& ref(void* ptr) { return *static_cast(ptr); } static const T& ref(const void* ptr) { return cref(ptr); } static const T& cref(const void* ptr) { return *static_cast(ptr); } template static Ptr ret(T&& val) { return {getAnyType(), &val}; } template static Ptr ret(RTag, T&& val) { return ret(std::forward(val)); } static void delete_(void* ptr) { delete static_cast(ptr); } static void* make(void* ptr, bool consume) { if (ptr == nullptr) { return std::make_unique().release(); } else if (consume) { return std::make_unique(std::move(ref(ptr))).release(); } else { return std::make_unique(cref(ptr)).release(); } } static bool empty(const void* ptr) { return op::isEmpty(ref(ptr)); } static void clear(void* ptr) { op::clear(ref(ptr)); } static void assign(void* ptr, const Dyn& val) { ref(ptr) = val.as(); } static bool identical(const void* lhs, const Dyn& rhs) { // Caller should have already checked the types match. assert(rhs.type() == Tag{}); return op::identical(ref(lhs), rhs.as()); } static folly::partial_ordering compare(const void* lhs, const Dyn& rhs) { if (const T* ptr = rhs.tryAs()) { return partialCmp(ref(lhs), *ptr); } // TODO(afuller): Throw bad_op() when all compatible type overloads are // implemented. unimplemented(); } private: template static if_comparable partialCmp(const T& lhs, const T& rhs) { return op::compare(lhs, rhs); } template static if_not_comparable partialCmp(const T& lhs, const T& rhs) { return op::equal(lhs, rhs) ? folly::partial_ordering::equivalent : folly::partial_ordering::unordered; } }; } // namespace detail } // namespace op } // namespace thrift } // namespace apache