/* * 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 #include #include #include namespace apache::thrift { enum class FunctionQualifier : uint8_t { Unspecified, OneWay, Idempotent, ReadOnly, }; enum class InteractionMethodPosition : uint8_t { None, Factory, Member, }; inline std::string_view qualifierToString(FunctionQualifier fq) { switch (fq) { case FunctionQualifier::Unspecified: return "Unspecified"; case FunctionQualifier::OneWay: return "OneWay"; case FunctionQualifier::Idempotent: return "Idempotent"; case FunctionQualifier::ReadOnly: return "ReadOnly"; } folly::assume_unreachable(); } /* * A structure for storing thrift method metadata. * When created from static data, the structure creates a view of the data * When created from temporary data, the structure takes the ownership of * the data by creating a dynamic storage for it. */ class MethodMetadata { public: struct Data { Data( std::string name, FunctionQualifier qualifier, std::string uriOrName = {}, InteractionMethodPosition position = InteractionMethodPosition::None, std::string interaction = {}) : methodName(std::move(name)), functionQualifier(qualifier), thriftServiceUriOrName(std::move(uriOrName)), interactionPosition(position), interactionName(std::move(interaction)) {} [[FOLLY_ATTR_GNU_COLD]] Data( const char* name, FunctionQualifier qualifier, const char* uriOrName = "", InteractionMethodPosition position = InteractionMethodPosition::None, const char* interaction = "") noexcept : methodName(name), functionQualifier(qualifier), thriftServiceUriOrName(uriOrName), interactionPosition(position), interactionName(interaction) {} std::string methodName; FunctionQualifier functionQualifier; std::string thriftServiceUriOrName; InteractionMethodPosition interactionPosition; std::string interactionName; }; MethodMetadata(const MethodMetadata& that) { if (that.isOwning()) { isOwning_ = true; data_ = new Data(*that.data_); } else { isOwning_ = false; data_ = that.data_; } } MethodMetadata& operator=(const MethodMetadata& that) { if (that.isOwning()) { if (isOwning()) { *data_ = *that.data_; } else { isOwning_ = true; data_ = new Data(*that.data_); } } else { if (isOwning()) { delete data_; isOwning_ = false; } data_ = that.data_; } return *this; } MethodMetadata(MethodMetadata&& that) noexcept : isOwning_(std::exchange(that.isOwning_, false)), data_(std::exchange(that.data_, nullptr)) {} MethodMetadata& operator=(MethodMetadata&& that) noexcept { MethodMetadata tmp(std::move(that)); swap(*this, tmp); return *this; } ~MethodMetadata() noexcept { if (isOwning()) { delete data_; } } /* implicit */ MethodMetadata(std::string_view methodName) : MethodMetadata( std::in_place, std::string(methodName), FunctionQualifier::Unspecified) {} /* implicit */ MethodMetadata(std::string&& methodName) : MethodMetadata( std::in_place, std::move(methodName), FunctionQualifier::Unspecified) {} /* implicit */ MethodMetadata(const std::string& methodName) : MethodMetadata( std::in_place, methodName, FunctionQualifier::Unspecified) {} /* implicit */ MethodMetadata(const char* methodName) : MethodMetadata( std::in_place, methodName, FunctionQualifier::Unspecified) {} /* implicit */ MethodMetadata(folly::StringPiece methodName) : MethodMetadata( std::in_place, std::string(methodName), FunctionQualifier::Unspecified) {} /* implicit */ MethodMetadata(const Data& data) : MethodMetadata(std::in_place, data) {} static MethodMetadata from_static(Data* mPtr) { return MethodMetadata(mPtr, NonOwningTag{}); } ManagedStringView name_managed() const& { if (isOwning()) { return ManagedStringView(name_view()); } else { return ManagedStringView::from_static(name_view()); } } ManagedStringView name_managed() && { if (isOwning()) { return ManagedStringView(std::move(data_->methodName)); } else { return ManagedStringView::from_static(name_view()); } } std::string name_str() const& { return data_->methodName; } std::string name_str() && { return isOwning() ? std::move(data_->methodName) : data_->methodName; } std::string_view name_view() const { return std::string_view(data_->methodName); } FunctionQualifier qualifier() const { return data_->functionQualifier; } ManagedStringView thriftServiceUriOrName_managed() const& { return isOwning() ? ManagedStringView(thriftServiceUriOrName_view()) : ManagedStringView::from_static(thriftServiceUriOrName_view()); } ManagedStringView thriftServiceUriOrName_managed() && { return isOwning() ? ManagedStringView(std::move(data_->thriftServiceUriOrName)) : ManagedStringView::from_static(thriftServiceUriOrName_view()); } std::string thriftServiceUriOrName_str() const& { return data_->thriftServiceUriOrName; } std::string thriftServiceUriOrName_str() && { return isOwning() ? std::move(data_->thriftServiceUriOrName) : data_->thriftServiceUriOrName; } std::string_view thriftServiceUriOrName_view() const { return data_->thriftServiceUriOrName; } InteractionMethodPosition interactionPosition() const { return data_->interactionPosition; } ManagedStringView interactionName_managed() const& { if (isOwning()) { return ManagedStringView(std::string_view(data_->interactionName)); } else { return ManagedStringView::from_static( std::string_view(data_->interactionName)); } } ManagedStringView interactionName_managed() && { if (isOwning()) { return ManagedStringView(std::move(data_->interactionName)); } else { return ManagedStringView::from_static( std::string_view(data_->interactionName)); } } bool isOwning() const { return isOwning_; } private: struct NonOwningTag {}; MethodMetadata(Data* mPtr, NonOwningTag) : isOwning_(false), data_(mPtr) {} template MethodMetadata(std::in_place_t, Args&&... args) : isOwning_(true), data_(new Data(std::forward(args)...)) {} friend void swap(MethodMetadata& left, MethodMetadata& right) noexcept { std::swap(left.isOwning_, right.isOwning_); std::swap(left.data_, right.data_); } bool isOwning_; Data* data_; }; } // namespace apache::thrift