blob: 78defa1d488d19765c77e5552c5148e41a7c43f3 [file] [log] [blame]
Feng Xiaoe96ff302015-06-15 18:21:48 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
32#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
33
34#include <functional>
35#include <google/protobuf/stubs/hash.h>
36#include <string>
37
38#include <google/protobuf/stubs/common.h>
39#include <google/protobuf/type.pb.h>
40#include <google/protobuf/util/internal/object_source.h>
41#include <google/protobuf/util/internal/object_writer.h>
42#include <google/protobuf/util/internal/type_info.h>
43#include <google/protobuf/util/type_resolver.h>
44#include <google/protobuf/stubs/stringpiece.h>
45#include <google/protobuf/stubs/status.h>
46#include <google/protobuf/stubs/statusor.h>
47
48
Feng Xiaoe96ff302015-06-15 18:21:48 -070049namespace google {
50namespace protobuf {
51class Field;
52class Type;
53} // namespace protobuf
54
55
56namespace protobuf {
57namespace util {
58namespace converter {
59
60class TypeInfo;
61
62// An ObjectSource that can parse a stream of bytes as a protocol buffer.
Feng Xiaoeee38b02015-08-22 18:25:48 -070063// Its WriteTo() method can be given an ObjectWriter.
64// This implementation uses a google.protobuf.Type for tag and name lookup.
65// The field names are converted into lower camel-case when writing to the
66// ObjectWriter.
Feng Xiaoe96ff302015-06-15 18:21:48 -070067//
68// Sample usage: (suppose input is: string proto)
69// ArrayInputStream arr_stream(proto.data(), proto.size());
70// CodedInputStream in_stream(&arr_stream);
71// ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo,
72// <your message google::protobuf::Type>);
73//
74// Status status = os.WriteTo(<some ObjectWriter>);
75class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
76 public:
77 ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
78 TypeResolver* type_resolver,
79 const google::protobuf::Type& type);
80
81 virtual ~ProtoStreamObjectSource();
82
83 virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const;
84
85 protected:
86 // Writes a proto2 Message to the ObjectWriter. When the given end_tag is
87 // found this method will complete, allowing it to be used for parsing both
88 // nested messages (end with 0) and nested groups (end with group end tag).
89 // The include_start_and_end parameter allows this method to be called when
90 // already inside of an object, and skip calling StartObject and EndObject.
91 virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
92 StringPiece name, const uint32 end_tag,
93 bool include_start_and_end,
94 ObjectWriter* ow) const;
95
96 private:
97 ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
Feng Xiaoeee38b02015-08-22 18:25:48 -070098 const TypeInfo* typeinfo,
Feng Xiaoe96ff302015-06-15 18:21:48 -070099 const google::protobuf::Type& type);
100 // Function that renders a well known type with a modified behavior.
101 typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
102 const google::protobuf::Type&,
103 StringPiece, ObjectWriter*);
104
105 // Looks up a field and verify its consistency with wire type in tag.
106 const google::protobuf::Field* FindAndVerifyField(
107 const google::protobuf::Type& type, uint32 tag) const;
108
109 // TODO(skarvaje): Mark these methods as non-const as they modify internal
110 // state (stream_).
111 //
112 // Renders a repeating field (packed or unpacked).
113 // Returns the next tag after reading all sequential repeating elements. The
114 // caller should use this tag before reading more tags from the stream.
115 util::StatusOr<uint32> RenderList(const google::protobuf::Field* field,
116 StringPiece name, uint32 list_tag,
117 ObjectWriter* ow) const;
118 // Renders a NWP map.
119 // Returns the next tag after reading all map entries. The caller should use
120 // this tag before reading more tags from the stream.
121 util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
122 StringPiece name, uint32 list_tag,
123 ObjectWriter* ow) const;
124
Feng Xiaoe96ff302015-06-15 18:21:48 -0700125 // Renders a packed repeating field. A packed field is stored as:
126 // {tag length item1 item2 item3} instead of the less efficient
127 // {tag item1 tag item2 tag item3}.
128 util::Status RenderPacked(const google::protobuf::Field* field,
129 ObjectWriter* ow) const;
130
Feng Xiaoe96ff302015-06-15 18:21:48 -0700131 // Renders a google.protobuf.Timestamp value to ObjectWriter
132 static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
133 const google::protobuf::Type& type,
134 StringPiece name, ObjectWriter* ow);
135
136 // Renders a google.protobuf.Duration value to ObjectWriter
137 static util::Status RenderDuration(const ProtoStreamObjectSource* os,
138 const google::protobuf::Type& type,
139 StringPiece name, ObjectWriter* ow);
140
141 // Following RenderTYPE functions render well known types in
142 // google/protobuf/wrappers.proto corresponding to TYPE.
143 static util::Status RenderDouble(const ProtoStreamObjectSource* os,
144 const google::protobuf::Type& type,
145 StringPiece name, ObjectWriter* ow);
146 static util::Status RenderFloat(const ProtoStreamObjectSource* os,
147 const google::protobuf::Type& type,
148 StringPiece name, ObjectWriter* ow);
149 static util::Status RenderInt64(const ProtoStreamObjectSource* os,
150 const google::protobuf::Type& type,
151 StringPiece name, ObjectWriter* ow);
152 static util::Status RenderUInt64(const ProtoStreamObjectSource* os,
153 const google::protobuf::Type& type,
154 StringPiece name, ObjectWriter* ow);
155 static util::Status RenderInt32(const ProtoStreamObjectSource* os,
156 const google::protobuf::Type& type,
157 StringPiece name, ObjectWriter* ow);
158 static util::Status RenderUInt32(const ProtoStreamObjectSource* os,
159 const google::protobuf::Type& type,
160 StringPiece name, ObjectWriter* ow);
161 static util::Status RenderBool(const ProtoStreamObjectSource* os,
162 const google::protobuf::Type& type,
163 StringPiece name, ObjectWriter* ow);
164 static util::Status RenderString(const ProtoStreamObjectSource* os,
165 const google::protobuf::Type& type,
166 StringPiece name, ObjectWriter* ow);
167 static util::Status RenderBytes(const ProtoStreamObjectSource* os,
168 const google::protobuf::Type& type,
169 StringPiece name, ObjectWriter* ow);
170
171 // Renders a google.protobuf.Struct to ObjectWriter.
172 static util::Status RenderStruct(const ProtoStreamObjectSource* os,
173 const google::protobuf::Type& type,
174 StringPiece name, ObjectWriter* ow);
175
176 // Helper to render google.protobuf.Struct's Value fields to ObjectWriter.
177 static util::Status RenderStructValue(const ProtoStreamObjectSource* os,
178 const google::protobuf::Type& type,
179 StringPiece name, ObjectWriter* ow);
180
181 // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter.
182 static util::Status RenderStructListValue(
Jisi Liu46e8ff62015-10-05 11:59:43 -0700183 const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
Feng Xiaoe96ff302015-06-15 18:21:48 -0700184 StringPiece name, ObjectWriter* ow);
185
186 // Render the "Any" type.
187 static util::Status RenderAny(const ProtoStreamObjectSource* os,
188 const google::protobuf::Type& type,
189 StringPiece name, ObjectWriter* ow);
190
191 // Render the "FieldMask" type.
192 static util::Status RenderFieldMask(const ProtoStreamObjectSource* os,
193 const google::protobuf::Type& type,
194 StringPiece name, ObjectWriter* ow);
195
Jisi Liu09778152015-08-25 22:01:12 -0700196 static hash_map<string, TypeRenderer>* renderers_;
197 static void InitRendererMap();
198 static void DeleteRendererMap();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700199 static TypeRenderer* FindTypeRenderer(const string& type_url);
200
201 // Renders a field value to the ObjectWriter.
202 util::Status RenderField(const google::protobuf::Field* field,
203 StringPiece field_name, ObjectWriter* ow) const;
204
Feng Xiaoe841bac2015-12-11 17:09:20 -0800205 // Same as above but renders all non-message field types. Callers don't call
206 // this function directly. They just use RenderField.
207 util::Status RenderNonMessageField(const google::protobuf::Field* field,
208 StringPiece field_name,
209 ObjectWriter* ow) const;
210
Jisi Liu46e8ff62015-10-05 11:59:43 -0700211
Feng Xiaoe96ff302015-06-15 18:21:48 -0700212 // Reads field value according to Field spec in 'field' and returns the read
213 // value as string. This only works for primitive datatypes (no message
214 // types).
215 const string ReadFieldValueAsString(
216 const google::protobuf::Field& field) const;
217
218 // Utility function to detect proto maps. The 'field' MUST be repeated.
219 bool IsMap(const google::protobuf::Field& field) const;
220
221 // Utility to read int64 and int32 values from a message type in stream_.
222 // Used for reading google.protobuf.Timestamp and Duration messages.
223 std::pair<int64, int32> ReadSecondsAndNanos(
224 const google::protobuf::Type& type) const;
225
226 // Input stream to read from. Ownership rests with the caller.
227 google::protobuf::io::CodedInputStream* stream_;
228
229 // Type information for all the types used in the descriptor. Used to find
230 // google::protobuf::Type of nested messages/enums.
Feng Xiaoeee38b02015-08-22 18:25:48 -0700231 const TypeInfo* typeinfo_;
Feng Xiaoe96ff302015-06-15 18:21:48 -0700232 // Whether this class owns the typeinfo_ object. If true the typeinfo_ object
233 // should be deleted in the destructor.
234 bool own_typeinfo_;
235
236 // google::protobuf::Type of the message source.
237 const google::protobuf::Type& type_;
238
Feng Xiaoe841bac2015-12-11 17:09:20 -0800239
Feng Xiaoe96ff302015-06-15 18:21:48 -0700240 GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
241};
242
243} // namespace converter
244} // namespace util
245} // namespace protobuf
246
247} // namespace google
248#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__