27
27
#include " Firestore/core/src/firebase/firestore/model/field_value.h"
28
28
#include " Firestore/core/src/firebase/firestore/model/no_document.h"
29
29
#include " Firestore/core/src/firebase/firestore/model/snapshot_version.h"
30
- #include " Firestore/core/src/firebase/firestore/nanopb/tag.h"
31
30
#include " Firestore/core/src/firebase/firestore/util/hard_assert.h"
31
+ #include " Firestore/core/src/firebase/firestore/util/string_format.h"
32
32
33
33
namespace firebase {
34
34
namespace firestore {
@@ -41,28 +41,27 @@ using model::NoDocument;
41
41
using model::ObjectValue;
42
42
using model::SnapshotVersion;
43
43
using nanopb::Reader;
44
- using nanopb::Tag;
45
44
using nanopb::Writer;
45
+ using remote::MakeArray;
46
46
using util::Status;
47
+ using util::StringFormat;
48
+
49
+ firestore_client_MaybeDocument LocalSerializer::EncodeMaybeDocument (
50
+ const MaybeDocument& maybe_doc) const {
51
+ firestore_client_MaybeDocument result{};
47
52
48
- void LocalSerializer::EncodeMaybeDocument (
49
- Writer* writer, const MaybeDocument& maybe_doc) const {
50
53
switch (maybe_doc.type ()) {
51
54
case MaybeDocument::Type::Document:
52
- writer->WriteTag (
53
- {PB_WT_STRING, firestore_client_MaybeDocument_document_tag});
54
- writer->WriteNestedMessage ([&](Writer* writer) {
55
- EncodeDocument (writer, static_cast <const Document&>(maybe_doc));
56
- });
57
- return ;
55
+ result.which_document_type = firestore_client_MaybeDocument_document_tag;
56
+ result.document = EncodeDocument (static_cast <const Document&>(maybe_doc));
57
+ return result;
58
58
59
59
case MaybeDocument::Type::NoDocument:
60
- writer->WriteTag (
61
- {PB_WT_STRING, firestore_client_MaybeDocument_no_document_tag});
62
- writer->WriteNestedMessage ([&](Writer* writer) {
63
- EncodeNoDocument (writer, static_cast <const NoDocument&>(maybe_doc));
64
- });
65
- return ;
60
+ result.which_document_type =
61
+ firestore_client_MaybeDocument_no_document_tag;
62
+ result.no_document =
63
+ EncodeNoDocument (static_cast <const NoDocument&>(maybe_doc));
64
+ return result;
66
65
67
66
case MaybeDocument::Type::Unknown:
68
67
// TODO(rsgowman)
@@ -73,195 +72,137 @@ void LocalSerializer::EncodeMaybeDocument(
73
72
}
74
73
75
74
std::unique_ptr<MaybeDocument> LocalSerializer::DecodeMaybeDocument (
76
- Reader* reader) const {
77
- std::unique_ptr<MaybeDocument> result;
78
-
79
- while (reader->good ()) {
80
- switch (reader->ReadTag ()) {
81
- case firestore_client_MaybeDocument_document_tag:
82
- // TODO(rsgowman): If multiple 'document' values are found, we should
83
- // merge them (rather than using the last one.)
84
- result = reader->ReadNestedMessage <Document>(
85
- rpc_serializer_, &remote::Serializer::DecodeDocument);
86
- break ;
87
-
88
- case firestore_client_MaybeDocument_no_document_tag:
89
- // TODO(rsgowman): If multiple 'no_document' values are found, we should
90
- // merge them (rather than using the last one.)
91
- result = reader->ReadNestedMessage <NoDocument>(
92
- *this , &LocalSerializer::DecodeNoDocument);
93
- break ;
94
-
95
- default :
96
- reader->SkipUnknown ();
97
- }
98
- }
75
+ Reader* reader, const firestore_client_MaybeDocument& proto) const {
76
+ if (!reader->status ().ok ()) return nullptr ;
99
77
100
- if (!result) {
101
- reader->Fail (
102
- " Invalid MaybeDocument message: Neither 'no_document' nor 'document' "
103
- " fields set." );
104
- return nullptr ;
78
+ switch (proto.which_document_type ) {
79
+ case firestore_client_MaybeDocument_document_tag:
80
+ return rpc_serializer_.DecodeDocument (reader, proto.document );
81
+
82
+ case firestore_client_MaybeDocument_no_document_tag:
83
+ return DecodeNoDocument (reader, proto.no_document );
84
+
85
+ default :
86
+ reader->Fail (
87
+ StringFormat (" Invalid MaybeDocument document type: %s. Expected "
88
+ " 'no_document' (%s) or 'document' (%s)" ,
89
+ proto.which_document_type ,
90
+ firestore_client_MaybeDocument_no_document_tag,
91
+ firestore_client_MaybeDocument_document_tag));
92
+ return nullptr ;
105
93
}
106
- return result;
94
+
95
+ UNREACHABLE ();
107
96
}
108
97
109
- void LocalSerializer::EncodeDocument (Writer* writer,
110
- const Document& doc) const {
111
- // Encode Document.name
112
- writer->WriteTag ({PB_WT_STRING, google_firestore_v1beta1_Document_name_tag});
113
- writer->WriteString (rpc_serializer_.EncodeKey (doc.key ()));
98
+ google_firestore_v1beta1_Document LocalSerializer::EncodeDocument (
99
+ const Document& doc) const {
100
+ google_firestore_v1beta1_Document result{};
101
+
102
+ result.name =
103
+ rpc_serializer_.EncodeString (rpc_serializer_.EncodeKey (doc.key ()));
114
104
115
105
// Encode Document.fields (unless it's empty)
116
- const ObjectValue& object_value = doc.data ().object_value ();
117
- if (!object_value.internal_value .empty ()) {
118
- rpc_serializer_.EncodeObjectMap (
119
- writer, object_value.internal_value ,
120
- google_firestore_v1beta1_Document_fields_tag,
121
- google_firestore_v1beta1_Document_FieldsEntry_key_tag,
122
- google_firestore_v1beta1_Document_FieldsEntry_value_tag);
106
+ size_t count = doc.data ().object_value ().internal_value .size ();
107
+ result.fields_count = count;
108
+ result.fields =
109
+ MakeArray<google_firestore_v1beta1_Document_FieldsEntry>(count);
110
+ int i = 0 ;
111
+ for (const auto & kv : doc.data ().object_value ().internal_value ) {
112
+ result.fields [i].key = rpc_serializer_.EncodeString (kv.first );
113
+ result.fields [i].value = rpc_serializer_.EncodeFieldValue (kv.second );
114
+ i++;
123
115
}
124
116
125
- // Encode Document.update_time
126
- writer->WriteTag (
127
- {PB_WT_STRING, google_firestore_v1beta1_Document_update_time_tag});
128
- writer->WriteNestedMessage ([&](Writer* writer) {
129
- rpc_serializer_.EncodeVersion (writer, doc.version ());
130
- });
117
+ result.update_time = rpc_serializer_.EncodeVersion (doc.version ());
131
118
132
119
// Ignore Document.create_time. (We don't use this in our on-disk protos.)
120
+
121
+ return result;
133
122
}
134
123
135
- void LocalSerializer::EncodeNoDocument (Writer* writer,
136
- const NoDocument& no_doc) const {
137
- // Encode NoDocument.name
138
- writer->WriteTag ({PB_WT_STRING, firestore_client_NoDocument_name_tag});
139
- writer->WriteString (rpc_serializer_.EncodeKey (no_doc.key ()));
140
-
141
- // Encode NoDocument.read_time
142
- writer->WriteTag ({PB_WT_STRING, firestore_client_NoDocument_read_time_tag});
143
- writer->WriteNestedMessage ([&](Writer* writer) {
144
- rpc_serializer_.EncodeVersion (writer, no_doc.version ());
145
- });
124
+ firestore_client_NoDocument LocalSerializer::EncodeNoDocument (
125
+ const NoDocument& no_doc) const {
126
+ firestore_client_NoDocument result{};
127
+
128
+ result.name =
129
+ rpc_serializer_.EncodeString (rpc_serializer_.EncodeKey (no_doc.key ()));
130
+ result.read_time = rpc_serializer_.EncodeVersion (no_doc.version ());
131
+
132
+ return result;
146
133
}
147
134
148
135
std::unique_ptr<NoDocument> LocalSerializer::DecodeNoDocument (
149
- Reader* reader) const {
150
- std::string name;
151
- absl::optional<SnapshotVersion> version = SnapshotVersion::None ();
152
-
153
- while (reader->good ()) {
154
- switch (reader->ReadTag ()) {
155
- case firestore_client_NoDocument_name_tag:
156
- name = reader->ReadString ();
157
- break ;
158
-
159
- case firestore_client_NoDocument_read_time_tag:
160
- version = reader->ReadNestedMessage <SnapshotVersion>(
161
- rpc_serializer_.DecodeSnapshotVersion );
162
- break ;
163
-
164
- default :
165
- reader->SkipUnknown ();
166
- break ;
167
- }
168
- }
169
-
136
+ Reader* reader, const firestore_client_NoDocument& proto) const {
170
137
if (!reader->status ().ok ()) return nullptr ;
171
- return absl::make_unique<NoDocument>(rpc_serializer_.DecodeKey (name),
172
- *std::move (version));
173
- }
174
138
175
- void LocalSerializer::EncodeQueryData (Writer* writer,
176
- const QueryData& query_data) const {
177
- writer->WriteTag ({PB_WT_VARINT, firestore_client_Target_target_id_tag});
178
- writer->WriteInteger (query_data.target_id ());
139
+ SnapshotVersion version =
140
+ rpc_serializer_.DecodeSnapshotVersion (reader, proto.read_time );
179
141
180
- writer->WriteTag (
181
- {PB_WT_VARINT, firestore_client_Target_last_listen_sequence_number_tag});
182
- writer->WriteInteger (query_data.sequence_number ());
142
+ if (!reader->status ().ok ()) return nullptr ;
143
+ return absl::make_unique<NoDocument>(
144
+ rpc_serializer_.DecodeKey (reader,
145
+ rpc_serializer_.DecodeString (proto.name )),
146
+ std::move (version));
147
+ }
183
148
184
- writer->WriteTag (
185
- {PB_WT_STRING, firestore_client_Target_snapshot_version_tag});
186
- writer->WriteNestedMessage ([&](Writer* writer) {
187
- rpc_serializer_.EncodeTimestamp (writer,
188
- query_data.snapshot_version ().timestamp ());
189
- });
149
+ firestore_client_Target LocalSerializer::EncodeQueryData (
150
+ const QueryData& query_data) const {
151
+ firestore_client_Target result{};
190
152
191
- writer->WriteTag ({PB_WT_STRING, firestore_client_Target_resume_token_tag});
192
- writer->WriteBytes (query_data.resume_token ());
153
+ result.target_id = query_data.target_id ();
154
+ result.last_listen_sequence_number = query_data.sequence_number ();
155
+ result.snapshot_version = rpc_serializer_.EncodeTimestamp (
156
+ query_data.snapshot_version ().timestamp ());
157
+ result.resume_token = rpc_serializer_.EncodeBytes (query_data.resume_token ());
193
158
194
159
const Query& query = query_data.query ();
195
160
if (query.IsDocumentQuery ()) {
196
161
// TODO(rsgowman): Implement. Probably like this (once EncodeDocumentsTarget
197
162
// exists):
198
163
/*
199
- writer->WriteTag({PB_WT_STRING, firestore_client_Target_documents_tag});
200
- writer->WriteNestedMessage([&](Writer* writer) {
201
- rpc_serializer_.EncodeDocumentsTarget(writer, query);
202
- });
164
+ result.which_target_type = firestore_client_Target_document_tag;
165
+ result.documents = rpc_serializer_.EncodeDocumentsTarget(query);
203
166
*/
204
167
abort ();
205
168
} else {
206
- writer->WriteTag ({PB_WT_STRING, firestore_client_Target_query_tag});
207
- writer->WriteNestedMessage ([&](Writer* writer) {
208
- rpc_serializer_.EncodeQueryTarget (writer, query);
209
- });
169
+ result.which_target_type = firestore_client_Target_query_tag;
170
+ result.query = rpc_serializer_.EncodeQueryTarget (query);
210
171
}
172
+
173
+ return result;
211
174
}
212
175
213
- absl::optional<QueryData> LocalSerializer::DecodeQueryData (
214
- Reader* reader) const {
215
- model::TargetId target_id = 0 ;
216
- model::ListenSequenceNumber sequence_number = 0 ;
217
- absl::optional<SnapshotVersion> version = SnapshotVersion::None ();
218
- std::vector<uint8_t > resume_token;
219
- absl::optional<Query> query = Query::Invalid ();
220
-
221
- while (reader->good ()) {
222
- switch (reader->ReadTag ()) {
223
- case firestore_client_Target_target_id_tag:
224
- // TODO(rsgowman): How to handle truncation of integer types?
225
- target_id = static_cast <model::TargetId>(reader->ReadInteger ());
226
- break ;
227
-
228
- case firestore_client_Target_last_listen_sequence_number_tag:
229
- // TODO(rsgowman): How to handle truncation of integer types?
230
- sequence_number =
231
- static_cast <model::ListenSequenceNumber>(reader->ReadInteger ());
232
- break ;
233
-
234
- case firestore_client_Target_snapshot_version_tag:
235
- version = reader->ReadNestedMessage <SnapshotVersion>(
236
- rpc_serializer_.DecodeSnapshotVersion );
237
- break ;
238
-
239
- case firestore_client_Target_resume_token_tag:
240
- resume_token = reader->ReadBytes ();
241
- break ;
242
-
243
- case firestore_client_Target_query_tag:
244
- // TODO(rsgowman): Clear 'documents' field (since query and documents
245
- // are part of a 'oneof').
246
- query =
247
- reader->ReadNestedMessage <Query>(rpc_serializer_.DecodeQueryTarget );
248
- break ;
249
-
250
- case firestore_client_Target_documents_tag:
251
- // Clear 'query' field (since query and documents are part of a 'oneof')
252
- query = Query::Invalid ();
253
- // TODO(rsgowman): Implement.
254
- abort ();
255
-
256
- default :
257
- reader->SkipUnknown ();
258
- break ;
259
- }
176
+ QueryData LocalSerializer::DecodeQueryData (
177
+ Reader* reader, const firestore_client_Target& proto) const {
178
+ if (!reader->status ().ok ()) return QueryData::Invalid ();
179
+
180
+ model::TargetId target_id = proto.target_id ;
181
+ // TODO(rgowman): How to handle truncation of integer types?
182
+ model::ListenSequenceNumber sequence_number = static_cast <model::ListenSequenceNumber>(proto.last_listen_sequence_number );
183
+ SnapshotVersion version =
184
+ rpc_serializer_.DecodeSnapshotVersion (reader, proto.snapshot_version );
185
+ std::vector<uint8_t > resume_token =
186
+ rpc_serializer_.DecodeBytes (proto.resume_token );
187
+ Query query = Query::Invalid ();
188
+
189
+ switch (proto.which_target_type ) {
190
+ case firestore_client_Target_query_tag:
191
+ query = rpc_serializer_.DecodeQueryTarget (reader, proto.query );
192
+ break ;
193
+
194
+ case firestore_client_Target_documents_tag:
195
+ // TODO(rsgowman): Implement.
196
+ abort ();
197
+
198
+ default :
199
+ reader->Fail (
200
+ StringFormat (" Unknown target_type: %s" , proto.which_target_type ));
260
201
}
261
202
262
- if (!reader->status ().ok ()) return absl::nullopt ;
263
- return QueryData (* std::move (query), target_id, sequence_number,
264
- QueryPurpose::kListen , * std::move (version),
203
+ if (!reader->status ().ok ()) return QueryData::Invalid () ;
204
+ return QueryData (std::move (query), target_id, sequence_number,
205
+ QueryPurpose::kListen , std::move (version),
265
206
std::move (resume_token));
266
207
}
267
208
0 commit comments