// 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_OBJECTWRITER_H__
#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__

#include <deque>
#include <google/protobuf/stubs/hash.h>
#include <string>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/type_info.h>
#include <google/protobuf/util/internal/datapiece.h>
#include <google/protobuf/util/internal/error_listener.h>
#include <google/protobuf/util/internal/proto_writer.h>
#include <google/protobuf/util/internal/structured_objectwriter.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/stubs/bytestream.h>

namespace google {
namespace protobuf {
namespace io {
class CodedOutputStream;
}  // namespace io
}  // namespace protobuf


namespace protobuf {
class Type;
class Field;
}  // namespace protobuf


namespace protobuf {
namespace util {
namespace converter {

class ObjectLocationTracker;

// An ObjectWriter that can write protobuf bytes directly from writer events.
// This class supports all special types like Struct and Map. It uses
// the ProtoWriter class to write raw proto bytes.
//
// It also supports streaming.
class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
 public:
  // Options that control ProtoStreamObjectWriter class's behavior.
  struct Options {
    // Treats integer inputs in google.protobuf.Struct as strings. Normally,
    // integer values are returned in double field "number_value" of
    // google.protobuf.Struct. However, this can cause precision loss for
    // int64/uint64 inputs. This option is provided for cases that want to
    // preserve integer precision.
    bool struct_integers_as_strings;

    Options() : struct_integers_as_strings(false) {}

    // Default instance of Options with all options set to defaults.
    static const Options& Defaults() {
      static Options defaults;
      return defaults;
    }
  };

// Constructor. Does not take ownership of any parameter passed in.
  ProtoStreamObjectWriter(TypeResolver* type_resolver,
                          const google::protobuf::Type& type,
                          strings::ByteSink* output, ErrorListener* listener,
                          const ProtoStreamObjectWriter::Options& options =
                              ProtoStreamObjectWriter::Options::Defaults());
  virtual ~ProtoStreamObjectWriter();

  // ObjectWriter methods.
  virtual ProtoStreamObjectWriter* StartObject(StringPiece name);
  virtual ProtoStreamObjectWriter* EndObject();
  virtual ProtoStreamObjectWriter* StartList(StringPiece name);
  virtual ProtoStreamObjectWriter* EndList();

  // Renders a DataPiece 'value' into a field whose wire type is determined
  // from the given field 'name'.
  virtual ProtoStreamObjectWriter* RenderDataPiece(StringPiece name,
                                                   const DataPiece& value);

 protected:
  // Function that renders a well known type with modified behavior.
  typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
                                         const DataPiece&);

  // Handles writing Anys out using nested object writers and the like.
  class LIBPROTOBUF_EXPORT AnyWriter {
   public:
    explicit AnyWriter(ProtoStreamObjectWriter* parent);
    ~AnyWriter();

    // Passes a StartObject call through to the Any writer.
    void StartObject(StringPiece name);

    // Passes an EndObject call through to the Any. Returns true if the any
    // handled the EndObject call, false if the Any is now all done and is no
    // longer needed.
    bool EndObject();

    // Passes a StartList call through to the Any writer.
    void StartList(StringPiece name);

    // Passes an EndList call through to the Any writer.
    void EndList();

    // Renders a data piece on the any.
    void RenderDataPiece(StringPiece name, const DataPiece& value);

   private:
    // Handles starting up the any once we have a type.
    void StartAny(const DataPiece& value);

    // Writes the Any out to the parent writer in its serialized form.
    void WriteAny();

    // The parent of this writer, needed for various bits such as type info and
    // the listeners.
    ProtoStreamObjectWriter* parent_;

    // The nested object writer, used to write events.
    google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;

    // The type_url_ that this Any represents.
    string type_url_;

    // Whether this any is invalid. This allows us to only report an invalid
    // Any message a single time rather than every time we get a nested field.
    bool invalid_;

    // The output data and wrapping ByteSink.
    string data_;
    strings::StringByteSink output_;

    // The depth within the Any, so we can track when we're done.
    int depth_;

    // True if the message type contained in Any has a special "value" message
    // injected. This is true for well-known message types like Any or Struct.
    bool has_injected_value_message_;
  };

  // Represents an item in a stack of items used to keep state between
  // ObjectWrier events.
  class LIBPROTOBUF_EXPORT Item : public BaseElement {
   public:
    // Indicates the type of item.
    enum ItemType {
      MESSAGE,  // Simple message
      MAP,      // Proto3 map type
      ANY,      // Proto3 Any type
    };

    // Constructor for the root item.
    Item(ProtoStreamObjectWriter* enclosing, ItemType item_type,
         bool is_placeholder, bool is_list);

    // Constructor for a field of a message.
    Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list);

    virtual ~Item() {}

    // These functions return true if the element type is corresponding to the
    // type in function name.
    bool IsMap() { return item_type_ == MAP; }
    bool IsAny() { return item_type_ == ANY; }

    AnyWriter* any() const { return any_.get(); }

    virtual Item* parent() const {
      return static_cast<Item*>(BaseElement::parent());
    }

    // Inserts map key into hash set if and only if the key did NOT already
    // exist in hash set.
    // The hash set (map_keys_) is ONLY used to keep track of map keys.
    // Return true if insert successfully; returns false if the map key was
    // already present.
    bool InsertMapKeyIfNotPresent(StringPiece map_key);

    bool is_placeholder() const { return is_placeholder_; }
    bool is_list() const { return is_list_; }

   private:
    // Used for access to variables of the enclosing instance of
    // ProtoStreamObjectWriter.
    ProtoStreamObjectWriter* ow_;

    // A writer for Any objects, handles all Any-related nonsense.
    google::protobuf::scoped_ptr<AnyWriter> any_;

    // The type of this element, see enum for permissible types.
    ItemType item_type_;

    // Set of map keys already seen for the type_. Used to validate incoming
    // messages so no map key appears more than once.
    hash_set<string> map_keys_;

    // Conveys whether this Item is a placeholder or not. Placeholder items are
    // pushed to stack to account for special types.
    bool is_placeholder_;

    // Conveys whether this Item is a list or not. This is used to send
    // StartList or EndList calls to underlying ObjectWriter.
    bool is_list_;

    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Item);
  };

  ProtoStreamObjectWriter(const TypeInfo* typeinfo,
                          const google::protobuf::Type& type,
                          strings::ByteSink* output, ErrorListener* listener);

  // Returns true if the field is a map.
  bool IsMap(const google::protobuf::Field& field);

  // Returns true if the field is an any.
  bool IsAny(const google::protobuf::Field& field);

  // Returns true if the field is google.protobuf.Struct.
  bool IsStruct(const google::protobuf::Field& field);

  // Returns true if the field is google.protobuf.Value.
  bool IsStructValue(const google::protobuf::Field& field);

  // Returns true if the field is google.protobuf.ListValue.
  bool IsStructListValue(const google::protobuf::Field& field);

  // Renders google.protobuf.Value in struct.proto. It picks the right oneof
  // type based on value's type.
  static util::Status RenderStructValue(ProtoStreamObjectWriter* ow,
                                          const DataPiece& value);

  // Renders google.protobuf.Timestamp value.
  static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
                                        const DataPiece& value);

  // Renders google.protobuf.FieldMask value.
  static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
                                        const DataPiece& value);

  // Renders google.protobuf.Duration value.
  static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
                                       const DataPiece& value);

  // Renders wrapper message types for primitive types in
  // google/protobuf/wrappers.proto.
  static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
                                          const DataPiece& value);

  static void InitRendererMap();
  static void DeleteRendererMap();
  static TypeRenderer* FindTypeRenderer(const string& type_url);

  // Returns true if the map key for type_ is not duplicated key.
  // If map key is duplicated key, this function returns false.
  // Note that caller should make sure that the current proto element (current_)
  // is of element type MAP or STRUCT_MAP.
  // It also calls the appropriate error callback and unnormalzied_name is used
  // for error string.
  bool ValidMapKey(StringPiece unnormalized_name);

  // Pushes an item on to the stack. Also calls either StartObject or StartList
  // on the underlying ObjectWriter depending on whether is_list is false or
  // not.
  // is_placeholder conveys whether the item is a placeholder item or not.
  // Placeholder items are pushed when adding auxillary types' StartObject or
  // StartList calls.
  void Push(StringPiece name, Item::ItemType item_type, bool is_placeholder,
            bool is_list);

  // Pops items from the stack. All placeholder items are popped until a
  // non-placeholder item is found.
  void Pop();

  // Pops one element from the stack. Calls EndObject() or EndList() on the
  // underlying ObjectWriter depending on the value of is_list_.
  void PopOneElement();

 private:
  // Helper functions to create the map and find functions responsible for
  // rendering well known types, keyed by type URL.
  static hash_map<string, TypeRenderer>* renderers_;

  // Variables for describing the structure of the input tree:
  // master_type_: descriptor for the whole protobuf message.
  const google::protobuf::Type& master_type_;

  // The current element, variable for internal state processing.
  google::protobuf::scoped_ptr<Item> current_;

  // Reference to the options that control this class's behavior.
  const ProtoStreamObjectWriter::Options options_;

  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
};

}  // namespace converter
}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__
