thrift/lib/cpp2/protocol/DebugProtocol.h (140 lines of code) (raw):

/* * 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. */ #ifndef CPP2_PROTOCOL_DEBUGPROTOCOL_H_ #define CPP2_PROTOCOL_DEBUGPROTOCOL_H_ #include <fmt/core.h> #include <folly/io/Cursor.h> #include <folly/io/IOBuf.h> #include <folly/portability/GFlags.h> #include <thrift/lib/cpp2/Thrift.h> #include <thrift/lib/cpp2/protocol/Cpp2Ops.h> #include <thrift/lib/cpp2/protocol/Protocol.h> DECLARE_bool(thrift_cpp2_debug_skip_list_indices); DECLARE_int64(thrift_cpp2_debug_string_limit); namespace apache { namespace thrift { class DebugProtocolWriter { public: struct Options { Options() {} bool skipListIndices = FLAGS_thrift_cpp2_debug_skip_list_indices; size_t stringLengthLimit = FLAGS_thrift_cpp2_debug_string_limit; }; using ProtocolReader = void; explicit DebugProtocolWriter( ExternalBufferSharing sharing = COPY_EXTERNAL_BUFFER /* ignored */, Options options = Options{}); static constexpr ProtocolType protocolType() { return ProtocolType::T_DEBUG_PROTOCOL; } static constexpr bool kSortKeys() { return true; } static constexpr bool kHasIndexSupport() { return false; } void setOutput( folly::IOBufQueue* queue, size_t maxGrowth = std::numeric_limits<size_t>::max()); void setOutput(folly::io::QueueAppender&& output); uint32_t writeMessageBegin( const std::string& name, MessageType messageType, int32_t seqid); uint32_t writeMessageEnd(); uint32_t writeStructBegin(const char* name); uint32_t writeStructEnd(); uint32_t writeFieldBegin(const char* name, TType fieldType, int16_t fieldId); uint32_t writeFieldEnd(); uint32_t writeFieldStop(); uint32_t writeMapBegin(TType keyType, TType valType, uint32_t size); uint32_t writeMapEnd(); uint32_t writeListBegin(TType elemType, uint32_t size); uint32_t writeListEnd(); uint32_t writeSetBegin(TType elemType, uint32_t size); uint32_t writeSetEnd(); uint32_t writeBool(bool value); uint32_t writeByte(int8_t byte); uint32_t writeI16(int16_t i16); uint32_t writeI32(int32_t i32); uint32_t writeI64(int64_t i64); uint32_t writeDouble(double dub); uint32_t writeFloat(float flt); uint32_t writeString(folly::StringPiece str); uint32_t writeBinary(folly::StringPiece str); uint32_t writeBinary(folly::ByteRange v); uint32_t writeBinary(const std::unique_ptr<folly::IOBuf>& str); uint32_t writeBinary(const folly::IOBuf& str); /** * Functions that return the serialized size */ uint32_t serializedMessageSize(const std::string& name); uint32_t serializedFieldSize( const char* name, TType fieldName, int16_t fieldId); uint32_t serializedStructSize(const char* name); uint32_t serializedSizeMapBegin(TType keyType, TType valType, uint32_t size); uint32_t serializedSizeMapEnd(); uint32_t serializedSizeListBegin(TType elemType, uint32_t size); uint32_t serializedSizeListEnd(); uint32_t serializedSizeSetBegin(TType elemType, uint32_t size); uint32_t serializedSizeSetEnd(); uint32_t serializedSizeStop(); uint32_t serializedSizeBool(bool value); uint32_t serializedSizeByte(int8_t byte); uint32_t serializedSizeI16(int16_t i16); uint32_t serializedSizeI32(int32_t i32); uint32_t serializedSizeI64(int64_t i64); uint32_t serializedSizeDouble(double dub); uint32_t serializedSizeFloat(float flt); uint32_t serializedSizeString(folly::StringPiece str); uint32_t serializedSizeBinary(folly::StringPiece str); uint32_t serializedSizeBinary(folly::ByteRange v); uint32_t serializedSizeBinary(const std::unique_ptr<folly::IOBuf>& v); uint32_t serializedSizeBinary(const folly::IOBuf& v); uint32_t serializedSizeZCBinary(folly::StringPiece str); uint32_t serializedSizeZCBinary(folly::ByteRange v); uint32_t serializedSizeZCBinary(const std::unique_ptr<folly::IOBuf>&); uint32_t serializedSizeZCBinary(const folly::IOBuf& /*v*/); private: void indentUp(); void indentDown(); void startItem(); void endItem(); void writeByteRange(folly::ByteRange v); void writeRaw(folly::StringPiece sp) { out_.push(reinterpret_cast<uint8_t const*>(sp.data()), sp.size()); } template <class... Args> void writePlain(fmt::string_view fmt, const Args&... args) { writeRaw(fmt::vformat(fmt, {fmt::make_format_args(args...)})); } void writeIndent() { writeRaw(indent_); } template <class... Args> void writeIndented(Args&&... args) { writeIndent(); writePlain(std::forward<Args>(args)...); } template <class... Args> void writeItem(Args&&... args) { startItem(); writePlain(std::forward<Args>(args)...); endItem(); } enum ItemType { STRUCT, SET, MAP_KEY, MAP_VALUE, LIST }; struct WriteState { /* implicit */ WriteState(ItemType t) : type(t), index(0) {} ItemType type; int index; }; void pushState(ItemType t); void popState(); folly::io::QueueAppender out_; std::string indent_; std::vector<WriteState> writeState_; const Options options_; }; template <class T> std::string debugString( const T& obj, DebugProtocolWriter::Options options = {}) { folly::IOBufQueue queue; DebugProtocolWriter proto( COPY_EXTERNAL_BUFFER, // Ignored by constructor. options); proto.setOutput(&queue); Cpp2Ops<T>::write(&proto, &obj); auto buf = queue.move(); auto br = buf->coalesce(); return std::string(reinterpret_cast<const char*>(br.data()), br.size()); } } // namespace thrift } // namespace apache #endif /* CPP2_PROTOCOL_DEBUGPROTOCOL_H_ */