text: // Protocol Buffers - Google's data interchange format
  // Copyright 2008 Google Inc.  All rights reserved.
  // https://developers.google.com/protocol-buffers/
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  //     * Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  // copyright notice, this list of conditions and the following disclaimer
  // in the documentation and/or other materials provided with the
  // distribution.
  //     * Neither the name of Google Inc. nor the names of its
  // contributors may be used to endorse or promote products derived from
  // this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
  #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
  
  #include <functional>
  #include "stubs/hash.h"
  
  #include "stubs/common.h"
  #include "type.pb.h"
  #include "util/internal/object_source.h"
  #include "util/internal/object_writer.h"
  #include "util/internal/type_info.h"
  #include "util/type_resolver.h"
  #include <contrib/libs/protobuf/stubs/stringpiece.h>
  #include "stubs/status.h"
  #include "stubs/statusor.h"
  
  
  namespace google {
  namespace protobuf {
  class Field;
  class Type;
  }  // namespace protobuf
  
  
  namespace protobuf {
  namespace util {
  namespace converter {
  
  class TypeInfo;
  
  // An ObjectSource that can parse a stream of bytes as a protocol buffer.
  // Its WriteTo() method can be given an ObjectWriter.
  // This implementation uses a google.protobuf.Type for tag and name lookup.
  // The field names are converted into lower camel-case when writing to the
  // ObjectWriter.
  //
  // Sample usage: (suppose input is: string proto)
  //   ArrayInputStream arr_stream(proto.data(), proto.size());
  //   CodedInputStream in_stream(&arr_stream);
  //   ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo,
  //                              <your message google::protobuf::Type>);
  //
  //   Status status = os.WriteTo(<some ObjectWriter>);
  class /* LIBPROTOBUF_EXPORT */ ProtoStreamObjectSource : public ObjectSource {
   public:
    ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
                            TypeResolver* type_resolver,
                            const google::protobuf::Type& type);
  
    virtual ~ProtoStreamObjectSource();
  
    virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const;
  
    // Sets whether or not to use lowerCamelCase casing for enum values. If set to
    // false, enum values are output without any case conversions.
    //
    // For example, if we have an enum:
    // enum Type {
    //   ACTION_AND_ADVENTURE = 1;
    // }
    // Type type = 20;
    //
    // And this option is set to true. Then the rendered "type" field will have
    // the string "actionAndAdventure".
    // {
    //   ...
    //   "type": "actionAndAdventure",
    //   ...
    // }
    //
    // If set to false, the rendered "type" field will have the string
    // "ACTION_AND_ADVENTURE".
    // {
    //   ...
    //   "type": "ACTION_AND_ADVENTURE",
    //   ...
    // }
    void set_use_lower_camel_for_enums(bool value) {
      use_lower_camel_for_enums_ = value;
    }
  
    // Sets the max recursion depth of proto message to be deserialized. Proto
    // messages over this depth will fail to be deserialized.
    // Default value is 64.
    void set_max_recursion_depth(int max_depth) {
      max_recursion_depth_ = max_depth;
    }
  
  
   protected:
    // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
    // found this method will complete, allowing it to be used for parsing both
    // nested messages (end with 0) and nested groups (end with group end tag).
    // The include_start_and_end parameter allows this method to be called when
    // already inside of an object, and skip calling StartObject and EndObject.
    virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
                                        StringPiece name, const uint32 end_tag,
                                        bool include_start_and_end,
                                        ObjectWriter* ow) const;
  
   private:
    ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
                            const TypeInfo* typeinfo,
                            const google::protobuf::Type& type);
    // Function that renders a well known type with a modified behavior.
    typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
                                           const google::protobuf::Type&,
                                           StringPiece, ObjectWriter*);
  
    // Looks up a field and verify its consistency with wire type in tag.
    const google::protobuf::Field* FindAndVerifyField(
        const google::protobuf::Type& type, uint32 tag) const;
  
    // TODO(skarvaje): Mark these methods as non-const as they modify internal
    // state (stream_).
    //
    // Renders a repeating field (packed or unpacked).
    // Returns the next tag after reading all sequential repeating elements. The
    // caller should use this tag before reading more tags from the stream.
    util::StatusOr<uint32> RenderList(const google::protobuf::Field* field,
                                        StringPiece name, uint32 list_tag,
                                        ObjectWriter* ow) const;
    // Renders a NWP map.
    // Returns the next tag after reading all map entries. The caller should use
    // this tag before reading more tags from the stream.
    util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
                                       StringPiece name, uint32 list_tag,
                                       ObjectWriter* ow) const;
  
    // Renders a packed repeating field. A packed field is stored as:
    // {tag length item1 item2 item3} instead of the less efficient
    // {tag item1 tag item2 tag item3}.
    util::Status RenderPacked(const google::protobuf::Field* field,
                                ObjectWriter* ow) const;
  
    // Renders a google.protobuf.Timestamp value to ObjectWriter
    static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
                                          const google::protobuf::Type& type,
                                          StringPiece name, ObjectWriter* ow);
  
    // Renders a google.protobuf.Duration value to ObjectWriter
    static util::Status RenderDuration(const ProtoStreamObjectSource* os,
                                         const google::protobuf::Type& type,
                                         StringPiece name, ObjectWriter* ow);
  
    // Following RenderTYPE functions render well known types in
    // google/protobuf/wrappers.proto corresponding to TYPE.
    static util::Status RenderDouble(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
                                       StringPiece name, ObjectWriter* ow);
    static util::Status RenderFloat(const ProtoStreamObjectSource* os,
                                      const google::protobuf::Type& type,
                                      StringPiece name, ObjectWriter* ow);
    static util::Status RenderInt64(const ProtoStreamObjectSource* os,
                                      const google::protobuf::Type& type,
                                      StringPiece name, ObjectWriter* ow);
    static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
                                       StringPiece name, ObjectWriter* ow);
    static util::Status RenderInt32(const ProtoStreamObjectSource* os,
                                      const google::protobuf::Type& type,
                                      StringPiece name, ObjectWriter* ow);
    static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
                                       StringPiece name, ObjectWriter* ow);
    static util::Status RenderBool(const ProtoStreamObjectSource* os,
                                     const google::protobuf::Type& type,
                                     StringPiece name, ObjectWriter* ow);
    static util::Status RenderString(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
                                       StringPiece name, ObjectWriter* ow);
    static util::Status RenderBytes(const ProtoStreamObjectSource* os,
                                      const google::protobuf::Type& type,
                                      StringPiece name, ObjectWriter* ow);
  
    // Renders a google.protobuf.Struct to ObjectWriter.
    static util::Status RenderStruct(const ProtoStreamObjectSource* os,
                                       const google::protobuf::Type& type,
                                       StringPiece name, ObjectWriter* ow);
  
    // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
    static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
                                            const google::protobuf::Type& type,
                                            StringPiece name, ObjectWriter* ow);
  
    // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
    static util::Status RenderStructListValue(
        const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
        StringPiece name, ObjectWriter* ow);
  
    // Render the "Any" type.
    static util::Status RenderAny(const ProtoStreamObjectSource* os,
                                    const google::protobuf::Type& type,
                                    StringPiece name, ObjectWriter* ow);
  
    // Render the "FieldMask" type.
    static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
                                          const google::protobuf::Type& type,
                                          StringPiece name, ObjectWriter* ow);
  
    static hash_map<string, TypeRenderer>* renderers_;
    static void InitRendererMap();
    static void DeleteRendererMap();
    static TypeRenderer* FindTypeRenderer(const string& type_url);
  
    // Renders a field value to the ObjectWriter.
    util::Status RenderField(const google::protobuf::Field* field,
                               StringPiece field_name, ObjectWriter* ow) const;
  
    // Same as above but renders all non-message field types. Callers don't call
    // this function directly. They just use RenderField.
    util::Status RenderNonMessageField(const google::protobuf::Field* field,
                                         StringPiece field_name,
                                         ObjectWriter* ow) const;
  
  
    // Reads field value according to Field spec in 'field' and returns the read
    // value as string. This only works for primitive datatypes (no message
    // types).
    const string ReadFieldValueAsString(
        const google::protobuf::Field& field) const;
  
    // Utility function to detect proto maps. The 'field' MUST be repeated.
    bool IsMap(const google::protobuf::Field& field) const;
  
    // Utility to read int64 and int32 values from a message type in stream_.
    // Used for reading google.protobuf.Timestamp and Duration messages.
    std::pair<int64, int32> ReadSecondsAndNanos(
        const google::protobuf::Type& type) const;
  
    // Helper function to check recursion depth and increment it. It will return
    // Status::OK if the current depth is allowed. Otherwise an error is returned.
    // type_name and field_name are used for error reporting.
    util::Status IncrementRecursionDepth(StringPiece type_name,
                                           StringPiece field_name) const;
  
    // Input stream to read from. Ownership rests with the caller.
    google::protobuf::io::CodedInputStream* stream_;
  
    // Type information for all the types used in the descriptor. Used to find
    // google::protobuf::Type of nested messages/enums.
    const TypeInfo* typeinfo_;
    // Whether this class owns the typeinfo_ object. If true the typeinfo_ object
    // should be deleted in the destructor.
    bool own_typeinfo_;
  
    // google::protobuf::Type of the message source.
    const google::protobuf::Type& type_;
  
  
    // Whether to render enums using lowerCamelCase. Defaults to false.
    bool use_lower_camel_for_enums_;
  
    // Tracks current recursion depth.
    mutable int recursion_depth_;
  
    // Maximum allowed recursion depth.
    int max_recursion_depth_;
  
    // Whether to render unknown fields.
    bool render_unknown_fields_;
  
    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
  };
  
  }  // namespace converter
  }  // namespace util
  }  // namespace protobuf
  
  }  // namespace google
  #endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
  