text: /*
   * Copyright (c) Facebook, Inc. and its 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_VIRTUALPROTOCOL_H_
  #define CPP2_PROTOCOL_VIRTUALPROTOCOL_H_ 1
  
  #include <map>
  #include <memory>
  #include <string>
  #include <vector>
  
  #include <folly/FBString.h>
  #include <folly/io/Cursor.h>
  #include <thrift/lib/cpp/Thrift.h>
  #include <thrift/lib/cpp/protocol/TProtocol.h>
  #include <thrift/lib/cpp2/protocol/Protocol.h>
  
  namespace apache {
  namespace thrift {
  
  class VirtualReaderBase {
   public:
    VirtualReaderBase() {}
    virtual ~VirtualReaderBase() {}
  
    virtual ProtocolType protocolType() const = 0;
    virtual bool kUsesFieldNames() const = 0;
    virtual bool kOmitsContainerSizes() const = 0;
    virtual bool kOmitsStringSizes() const = 0;
    virtual bool kHasDeferredRead() const = 0;
  
    virtual void setInput(const folly::io::Cursor& cursor) = 0;
    void setInput(const folly::IOBuf* buf) { setInput(folly::io::Cursor(buf)); }
  
    virtual void readMessageBegin(
        std::string& name, MessageType& messageType, int32_t& seqid) = 0;
    virtual void readMessageEnd() = 0;
    virtual void readStructBegin(std::string& name) = 0;
    virtual void readStructEnd() = 0;
    virtual void readFieldBegin(
        std::string& name, TType& fieldType, int16_t& fieldId) = 0;
    virtual void readFieldEnd() = 0;
    virtual void readMapBegin(TType& keyType, TType& valType, uint32_t& size) = 0;
    virtual void readMapEnd() = 0;
    virtual void readListBegin(TType& elemType, uint32_t& size) = 0;
    virtual void readListEnd() = 0;
    virtual void readSetBegin(TType& elemType, uint32_t& size) = 0;
    virtual void readSetEnd() = 0;
    virtual void readBool(bool& value) = 0;
    virtual void readBool(std::vector<bool>::reference value) = 0;
    virtual void readByte(int8_t& byte) = 0;
    virtual void readI16(int16_t& i16) = 0;
    virtual void readI32(int32_t& i32) = 0;
    virtual void readI64(int64_t& i64) = 0;
    virtual void readDouble(double& dub) = 0;
    virtual void readFloat(float& flt) = 0;
    virtual void readString(std::string& str) = 0;
    virtual void readString(folly::fbstring& str) = 0;
    virtual void readBinary(std::string& str) = 0;
    virtual void readBinary(folly::fbstring& str) = 0;
    virtual void readBinary(apache::thrift::detail::SkipNoopString& str) = 0;
    virtual void readBinary(std::unique_ptr<folly::IOBuf>& str) = 0;
    virtual void readBinary(folly::IOBuf& str) = 0;
    virtual size_t fixedSizeInContainer(TType) const = 0;
    virtual void skipBytes(size_t bytes) = 0;
    virtual void skip(TType type) = 0;
    virtual const folly::io::Cursor& getCursor() const = 0;
    virtual size_t getCursorPosition() const = 0;
    virtual bool peekMap() { return false; }
    virtual bool peekSet() { return false; }
    virtual bool peekList() { return false; }
  };
  
  std::unique_ptr<VirtualReaderBase> makeVirtualReader(ProtocolType type);
  
  template <class ProtocolT>
  class VirtualReader : public VirtualReaderBase {
   public:
    using ProtocolWriter = typename ProtocolT::ProtocolWriter;
  
    template <
        typename... Args,
        typename std::enable_if<
            std::is_constructible<ProtocolT, Args...>::value,
            bool>::type = false>
    explicit VirtualReader(Args&&... args)
        : protocol_(std::forward<Args>(args)...) {}
    ~VirtualReader() override {}
  
    ProtocolType protocolType() const override {
      return protocol_.protocolType();
    }
  
    bool kUsesFieldNames() const override { return protocol_.kUsesFieldNames(); }
  
    virtual bool kOmitsContainerSizes() const override {
      return protocol_.kOmitsContainerSizes();
    }
  
    virtual bool kOmitsStringSizes() const override {
      return protocol_.kOmitsStringSizes();
    }
  
    virtual bool kHasDeferredRead() const override {
      return protocol_.kHasDeferredRead();
    }
  
    using VirtualReaderBase::setInput;
    void setInput(const folly::io::Cursor& cursor) override {
      protocol_.setInput(cursor);
    }
  
    void readMessageBegin(
        std::string& name, MessageType& messageType, int32_t& seqid) override {
      protocol_.readMessageBegin(name, messageType, seqid);
    }
    void readMessageEnd() override { protocol_.readMessageEnd(); }
    void readStructBegin(std::string& name) override {
      protocol_.readStructBegin(name);
    }
    void readStructEnd() override { protocol_.readStructEnd(); }
    void readFieldBegin(
        std::string& name, TType& fieldType, int16_t& fieldId) override {
      protocol_.readFieldBegin(name, fieldType, fieldId);
    }
    void readFieldEnd() override { protocol_.readFieldEnd(); }
    void readMapBegin(TType& keyType, TType& valType, uint32_t& size) override {
      protocol_.readMapBegin(keyType, valType, size);
    }
    void readMapEnd() override { protocol_.readMapEnd(); }
    void readListBegin(TType& elemType, uint32_t& size) override {
      protocol_.readListBegin(elemType, size);
    }
    void readListEnd() override { protocol_.readListEnd(); }
    void readSetBegin(TType& elemType, uint32_t& size) override {
      protocol_.readSetBegin(elemType, size);
    }
    void readSetEnd() override { protocol_.readSetEnd(); }
    void readBool(bool& value) override { protocol_.readBool(value); }
    void readBool(std::vector<bool>::reference value) override {
      protocol_.readBool(value);
    }
    void readByte(int8_t& byte) override { protocol_.readByte(byte); }
    void readI16(int16_t& i16) override { protocol_.readI16(i16); }
    void readI32(int32_t& i32) override { protocol_.readI32(i32); }
    void readI64(int64_t& i64) override { protocol_.readI64(i64); }
    void readDouble(double& dub) override { protocol_.readDouble(dub); }
    void readFloat(float& flt) override { protocol_.readFloat(flt); }
    void readString(std::string& str) override { protocol_.readString(str); }
    void readString(folly::fbstring& str) override { protocol_.readString(str); }
    void readBinary(std::string& str) override { protocol_.readBinary(str); }
    void readBinary(folly::fbstring& str) override { protocol_.readBinary(str); }
    virtual void readBinary(
        apache::thrift::detail::SkipNoopString& str) override {
      protocol_.readBinary(str);
    }
    void readBinary(std::unique_ptr<folly::IOBuf>& str) override {
      protocol_.readBinary(str);
    }
    void readBinary(folly::IOBuf& str) override { protocol_.readBinary(str); }
    size_t fixedSizeInContainer(TType type) const override {
      return protocol_.fixedSizeInContainer(type);
    }
    void skipBytes(size_t bytes) override { protocol_.skipBytes(bytes); }
    void skip(TType type) override { protocol_.skip(type); }
    const folly::io::Cursor& getCursor() const override {
      return protocol_.getCursor();
    }
    size_t getCursorPosition() const override {
      return protocol_.getCursorPosition();
    }
  
   protected:
    ProtocolT protocol_;
  };
  
  } // namespace thrift
  } // namespace apache
  
  #endif
  