20
20
#include < pb.h>
21
21
#include < pb_decode.h>
22
22
23
- #include < cstdint>
24
- #include < functional>
25
- #include < memory>
26
- #include < string>
27
- #include < utility>
28
- #include < vector>
29
-
30
23
#include " Firestore/core/include/firebase/firestore/firestore_errors.h"
31
- #include " Firestore/core/src/firebase/firestore/nanopb/tag.h"
32
- #include " Firestore/core/src/firebase/firestore/util/hard_assert.h"
33
24
#include " Firestore/core/src/firebase/firestore/util/status.h"
34
25
#include " absl/strings/string_view.h"
35
- #include " absl/types/optional.h"
36
26
37
27
namespace firebase {
38
28
namespace firestore {
@@ -59,25 +49,6 @@ class Reader {
59
49
*/
60
50
static Reader Wrap (const uint8_t * bytes, size_t length);
61
51
62
- /* *
63
- * Reads a message type from the input stream.
64
- *
65
- * This essentially wraps calls to nanopb's pb_decode_tag() method.
66
- *
67
- * In addition to returning the tag, this method also stores it. Subsequent
68
- * calls to ReadX will use the stored last tag to verify that the type is
69
- * correct (and will otherwise set the status of this Reader object to a
70
- * non-ok value with the code set to FirestoreErrorCode::DataLoss).
71
- *
72
- * @return The field number of the tag. Technically, this differs slightly
73
- * from the tag itself insomuch as it doesn't include the wire type.
74
- */
75
- uint32_t ReadTag ();
76
-
77
- const Tag& last_tag () const {
78
- return last_tag_;
79
- }
80
-
81
52
/* *
82
53
* Reads a nanopb message from the input stream.
83
54
*
@@ -102,83 +73,6 @@ class Reader {
102
73
*/
103
74
void FreeNanopbMessage (const pb_field_t fields[], void * dest_struct);
104
75
105
- void ReadNull ();
106
- bool ReadBool ();
107
- std::int64_t ReadInteger ();
108
-
109
- std::string ReadString ();
110
-
111
- std::vector<uint8_t > ReadBytes ();
112
-
113
- /* *
114
- * Reads a message and its length.
115
- *
116
- * Analog to Writer::WriteNestedMessage(). See that methods docs for further
117
- * details.
118
- *
119
- * Call this method when reading a nested message. Provide a function to read
120
- * the message itself. An overload exists to allow the function to return
121
- * either an optional or a unique_ptr.
122
- *
123
- * @param read_message_fn Function to read the submessage. Note that this
124
- * function should return {} (or nullptr/nullopt) on error.
125
- * @return Empty (i.e. nullptr/nullopt) on failure, else the deserialized
126
- * value.
127
- */
128
- template <typename T>
129
- absl::optional<T> ReadNestedMessage (
130
- const std::function<absl::optional<T>(Reader*)>& read_message_fn) {
131
- return ReadNestedMessageImpl (read_message_fn);
132
- }
133
- template <typename T>
134
- std::unique_ptr<T> ReadNestedMessage (
135
- const std::function<std::unique_ptr<T>(Reader*)>& read_message_fn) {
136
- return ReadNestedMessageImpl (read_message_fn);
137
- }
138
-
139
- template <typename T, typename C>
140
- using ReadingMemberFunction = T (C::*)(Reader*) const ;
141
-
142
- /* *
143
- * Reads a message and its length.
144
- *
145
- * Identical to ReadNestedMessage(), except this additionally takes the
146
- * serializer (either local or remote) as the first parameter, thus allowing
147
- * non-static methods to be used as the read_message_member_fn.
148
- */
149
- template <typename T, typename C>
150
- absl::optional<T> ReadNestedMessage (
151
- const C& serializer,
152
- ReadingMemberFunction<absl::optional<T>, C> read_message_member_fn) {
153
- return ReadNestedMessageImpl (serializer, read_message_member_fn);
154
- }
155
- template <typename T, typename C>
156
- std::unique_ptr<T> ReadNestedMessage (
157
- const C& serializer,
158
- ReadingMemberFunction<std::unique_ptr<T>, C> read_message_member_fn) {
159
- return ReadNestedMessageImpl (serializer, read_message_member_fn);
160
- }
161
-
162
- /* *
163
- * Discards the bytes associated with the last read tag. (According to the
164
- * proto spec, we must ignore unknown fields.)
165
- *
166
- * This method uses the last tag read via ReadTag to determine how many bytes
167
- * should be discarded.
168
- */
169
- void SkipUnknown ();
170
-
171
- size_t bytes_left () const {
172
- return stream_.bytes_left ;
173
- }
174
-
175
- /* *
176
- * True if the stream still has bytes left, and the status is ok.
177
- */
178
- bool good () const {
179
- return stream_.bytes_left && status_.ok ();
180
- }
181
-
182
76
util::Status status () const {
183
77
return status_;
184
78
}
@@ -208,95 +102,11 @@ class Reader {
208
102
explicit Reader (pb_istream_t stream) : stream_(stream) {
209
103
}
210
104
211
- /* *
212
- * Ensures the last read tag (set via ReadTag()) is of the specified type. If
213
- * not, then Reader::status() will return a non-ok value (with the code set to
214
- * FirestoreErrorCode::DataLoss).
215
- *
216
- * @return Convenience indicator for success. (If false, then status() will
217
- * return a non-ok value.)
218
- */
219
- bool RequireWireType (pb_wire_type_t wire_type);
220
-
221
- /* *
222
- * Reads a "varint" from the input stream.
223
- *
224
- * This essentially wraps calls to nanopb's pb_decode_varint() method.
225
- *
226
- * Note that (despite the return type) this works for bool, enum, int32,
227
- * int64, uint32 and uint64 proto field types.
228
- *
229
- * Note: This is not expected to be called direclty, but rather only via the
230
- * other Decode* methods (i.e. DecodeBool, DecodeLong, etc)
231
- *
232
- * @return The decoded varint as a uint64_t.
233
- */
234
- std::uint64_t ReadVarint ();
235
-
236
- template <typename T>
237
- T ReadNestedMessageImpl (const std::function<T(Reader*)>& read_message_fn);
238
-
239
- template <typename T, typename C>
240
- T ReadNestedMessageImpl (const C& serializer,
241
- ReadingMemberFunction<T, C> read_message_member_fn);
242
-
243
105
util::Status status_ = util::Status::OK();
244
106
245
107
pb_istream_t stream_;
246
-
247
- Tag last_tag_;
248
108
};
249
109
250
- template <typename T>
251
- T Reader::ReadNestedMessageImpl (
252
- const std::function<T(Reader*)>& read_message_fn) {
253
- // Implementation note: This is roughly modeled on pb_decode_delimited,
254
- // adjusted to account for the oneof in FieldValue.
255
-
256
- RequireWireType (PB_WT_STRING);
257
- if (!status_.ok ()) return {};
258
-
259
- pb_istream_t raw_substream;
260
- if (!pb_make_string_substream (&stream_, &raw_substream)) {
261
- status_ =
262
- util::Status (FirestoreErrorCode::DataLoss, PB_GET_ERROR (&stream_));
263
- return read_message_fn (this );
264
- }
265
- Reader substream (raw_substream);
266
-
267
- // If this fails, we *won't* return right away so that we can cleanup the
268
- // substream (although technically, that turns out not to matter; no resource
269
- // leaks occur if we don't do this.)
270
- // TODO(rsgowman): Consider RAII here. (Watch out for Reader class which also
271
- // wraps streams.)
272
- T message = read_message_fn (&substream);
273
- status_ = substream.status ();
274
-
275
- // NB: future versions of nanopb read the remaining characters out of the
276
- // substream (and return false if that fails) as an additional safety
277
- // check within pb_close_string_substream. Unfortunately, that's not present
278
- // in the current version (0.38). We'll make a stronger assertion and check
279
- // to make sure there *are* no remaining characters in the substream.
280
- HARD_ASSERT (
281
- substream.bytes_left () == 0 ,
282
- " Bytes remaining in substream after supposedly reading all of them." );
283
-
284
- pb_close_string_substream (&stream_, &substream.stream_ );
285
-
286
- return message;
287
- }
288
-
289
- template <typename T, typename C>
290
- T Reader::ReadNestedMessageImpl (
291
- const C& serializer,
292
- Reader::ReadingMemberFunction<T, C> read_message_member_fn) {
293
- std::function<T (Reader*)> read_message_fn = [=](Reader* reader) {
294
- return (serializer.*read_message_member_fn)(reader);
295
- };
296
-
297
- return ReadNestedMessageImpl (std::move (read_message_fn));
298
- }
299
-
300
110
} // namespace nanopb
301
111
} // namespace firestore
302
112
} // namespace firebase
0 commit comments