Skip to content

Commit 45ef270

Browse files
committed
Simplify Serializer Encode*() methods to no longer serialize manually.
Now, we use the re-worked nanopb deserializer (that mallocs). This also had the advantage of moving the C++ serialization code closer to the other platforms. Still TODO: - Reorder the methods within the files to resemble the other platforms. - Rework error handling.
1 parent 3cff51f commit 45ef270

File tree

6 files changed

+275
-245
lines changed

6 files changed

+275
-245
lines changed

Firestore/core/src/firebase/firestore/local/local_serializer.cc

Lines changed: 56 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,23 @@ using nanopb::Writer;
4747
using util::Status;
4848
using util::StringFormat;
4949

50-
void LocalSerializer::EncodeMaybeDocument(
51-
Writer* writer, const MaybeDocument& maybe_doc) const {
50+
firestore_client_MaybeDocument LocalSerializer::EncodeMaybeDocument(
51+
const MaybeDocument& maybe_doc) const {
52+
firestore_client_MaybeDocument result =
53+
firestore_client_MaybeDocument_init_zero;
54+
5255
switch (maybe_doc.type()) {
5356
case MaybeDocument::Type::Document:
54-
writer->WriteTag(
55-
{PB_WT_STRING, firestore_client_MaybeDocument_document_tag});
56-
writer->WriteNestedMessage([&](Writer* writer) {
57-
EncodeDocument(writer, static_cast<const Document&>(maybe_doc));
58-
});
59-
return;
57+
result.which_document_type = firestore_client_MaybeDocument_document_tag;
58+
result.document = EncodeDocument(static_cast<const Document&>(maybe_doc));
59+
return result;
6060

6161
case MaybeDocument::Type::NoDocument:
62-
writer->WriteTag(
63-
{PB_WT_STRING, firestore_client_MaybeDocument_no_document_tag});
64-
writer->WriteNestedMessage([&](Writer* writer) {
65-
EncodeNoDocument(writer, static_cast<const NoDocument&>(maybe_doc));
66-
});
67-
return;
62+
result.which_document_type =
63+
firestore_client_MaybeDocument_no_document_tag;
64+
result.no_document =
65+
EncodeNoDocument(static_cast<const NoDocument&>(maybe_doc));
66+
return result;
6867

6968
case MaybeDocument::Type::Unknown:
7069
// TODO(rsgowman)
@@ -95,43 +94,49 @@ std::unique_ptr<MaybeDocument> LocalSerializer::DecodeMaybeDocument(
9594
UNREACHABLE();
9695
}
9796

98-
void LocalSerializer::EncodeDocument(Writer* writer,
99-
const Document& doc) const {
97+
google_firestore_v1beta1_Document LocalSerializer::EncodeDocument(
98+
const Document& doc) const {
99+
google_firestore_v1beta1_Document result =
100+
google_firestore_v1beta1_Document_init_zero;
101+
100102
// Encode Document.name
101-
writer->WriteTag({PB_WT_STRING, google_firestore_v1beta1_Document_name_tag});
102-
writer->WriteString(rpc_serializer_.EncodeKey(doc.key()));
103+
result.name =
104+
rpc_serializer_.EncodeString(rpc_serializer_.EncodeKey(doc.key()));
103105

104106
// Encode Document.fields (unless it's empty)
105-
const ObjectValue& object_value = doc.data().object_value();
106-
if (!object_value.internal_value.empty()) {
107-
rpc_serializer_.EncodeObjectMap(
108-
writer, object_value.internal_value,
109-
google_firestore_v1beta1_Document_fields_tag,
110-
google_firestore_v1beta1_Document_FieldsEntry_key_tag,
111-
google_firestore_v1beta1_Document_FieldsEntry_value_tag);
107+
size_t count = doc.data().object_value().internal_value.size();
108+
result.fields_count = count;
109+
result.fields =
110+
reinterpret_cast<google_firestore_v1beta1_Document_FieldsEntry*>(malloc(
111+
sizeof(google_firestore_v1beta1_Document_FieldsEntry) * count));
112+
int i = 0;
113+
for (const auto& kv : doc.data().object_value().internal_value) {
114+
result.fields[i] = google_firestore_v1beta1_Document_FieldsEntry_init_zero;
115+
result.fields[i].key = rpc_serializer_.EncodeString(kv.first);
116+
result.fields[i].value = rpc_serializer_.EncodeFieldValue(kv.second);
117+
i++;
112118
}
113119

114120
// Encode Document.update_time
115-
writer->WriteTag(
116-
{PB_WT_STRING, google_firestore_v1beta1_Document_update_time_tag});
117-
writer->WriteNestedMessage([&](Writer* writer) {
118-
rpc_serializer_.EncodeVersion(writer, doc.version());
119-
});
121+
result.update_time = rpc_serializer_.EncodeVersion(doc.version());
120122

121123
// Ignore Document.create_time. (We don't use this in our on-disk protos.)
124+
125+
return result;
122126
}
123127

124-
void LocalSerializer::EncodeNoDocument(Writer* writer,
125-
const NoDocument& no_doc) const {
128+
firestore_client_NoDocument LocalSerializer::EncodeNoDocument(
129+
const NoDocument& no_doc) const {
130+
firestore_client_NoDocument result = firestore_client_NoDocument_init_zero;
131+
126132
// Encode NoDocument.name
127-
writer->WriteTag({PB_WT_STRING, firestore_client_NoDocument_name_tag});
128-
writer->WriteString(rpc_serializer_.EncodeKey(no_doc.key()));
133+
result.name =
134+
rpc_serializer_.EncodeString(rpc_serializer_.EncodeKey(no_doc.key()));
129135

130136
// Encode NoDocument.read_time
131-
writer->WriteTag({PB_WT_STRING, firestore_client_NoDocument_read_time_tag});
132-
writer->WriteNestedMessage([&](Writer* writer) {
133-
rpc_serializer_.EncodeVersion(writer, no_doc.version());
134-
});
137+
result.read_time = rpc_serializer_.EncodeVersion(no_doc.version());
138+
139+
return result;
135140
}
136141

137142
std::unique_ptr<NoDocument> LocalSerializer::DecodeNoDocument(
@@ -147,38 +152,30 @@ std::unique_ptr<NoDocument> LocalSerializer::DecodeNoDocument(
147152
*std::move(version));
148153
}
149154

150-
void LocalSerializer::EncodeQueryData(Writer* writer,
151-
const QueryData& query_data) const {
152-
writer->WriteTag({PB_WT_VARINT, firestore_client_Target_target_id_tag});
153-
writer->WriteInteger(query_data.target_id());
154-
155-
writer->WriteTag(
156-
{PB_WT_STRING, firestore_client_Target_snapshot_version_tag});
157-
writer->WriteNestedMessage([&](Writer* writer) {
158-
rpc_serializer_.EncodeTimestamp(writer,
159-
query_data.snapshot_version().timestamp());
160-
});
155+
firestore_client_Target LocalSerializer::EncodeQueryData(
156+
const QueryData& query_data) const {
157+
firestore_client_Target result = firestore_client_Target_init_zero;
161158

162-
writer->WriteTag({PB_WT_STRING, firestore_client_Target_resume_token_tag});
163-
writer->WriteBytes(query_data.resume_token());
159+
result.target_id = query_data.target_id();
160+
result.snapshot_version = rpc_serializer_.EncodeTimestamp(
161+
query_data.snapshot_version().timestamp());
162+
result.resume_token = rpc_serializer_.EncodeBytes(query_data.resume_token());
164163

165164
const Query& query = query_data.query();
166165
if (query.IsDocumentQuery()) {
167166
// TODO(rsgowman): Implement. Probably like this (once EncodeDocumentsTarget
168167
// exists):
169168
/*
170-
writer->WriteTag({PB_WT_STRING, firestore_client_Target_documents_tag});
171-
writer->WriteNestedMessage([&](Writer* writer) {
172-
rpc_serializer_.EncodeDocumentsTarget(writer, query);
173-
});
169+
result.which_target_type = firestore_client_Target_document_tag;
170+
result.documents = rpc_serializer_.EncodeDocumentsTarget(query);
174171
*/
175172
abort();
176173
} else {
177-
writer->WriteTag({PB_WT_STRING, firestore_client_Target_query_tag});
178-
writer->WriteNestedMessage([&](Writer* writer) {
179-
rpc_serializer_.EncodeQueryTarget(writer, query);
180-
});
174+
result.which_target_type = firestore_client_Target_query_tag;
175+
result.query = rpc_serializer_.EncodeQueryTarget(query);
181176
}
177+
178+
return result;
182179
}
183180

184181
absl::optional<QueryData> LocalSerializer::DecodeQueryData(

Firestore/core/src/firebase/firestore/local/local_serializer.h

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,22 @@ class LocalSerializer {
5252
}
5353

5454
/**
55-
* @brief Encodes a MaybeDocument model to the equivalent bytes for local
56-
* storage.
55+
* Release memory allocated by the Encode* methods that return protos.
5756
*
58-
* Any errors that occur during encoding are fatal.
57+
* This essentially wraps calls to nanopb's pb_release() method.
58+
*/
59+
static void FreeNanopbMessage(const pb_field_t fields[], void* dest_struct) {
60+
remote::Serializer::FreeNanopbMessage(fields, dest_struct);
61+
}
62+
63+
/**
64+
* @brief Encodes a MaybeDocument model to the equivalent nanopb proto for
65+
* local storage.
5966
*
60-
* @param writer The serialized output will be written to the provided writer.
61-
* @param maybe_doc the model to convert.
67+
* Any errors that occur during encoding are fatal.
6268
*/
63-
void EncodeMaybeDocument(nanopb::Writer* writer,
64-
const model::MaybeDocument& maybe_doc) const;
69+
firestore_client_MaybeDocument EncodeMaybeDocument(
70+
const model::MaybeDocument& maybe_doc) const;
6571

6672
/**
6773
* @brief Decodes nanopb proto representing a MaybeDocument proto to the
@@ -79,15 +85,12 @@ class LocalSerializer {
7985
const firestore_client_MaybeDocument& proto) const;
8086

8187
/**
82-
* @brief Encodes a QueryData to the equivalent bytes, representing a
88+
* @brief Encodes a QueryData to the equivalent nanopb proto, representing a
8389
* ::firestore::proto::Target, for local storage.
8490
*
8591
* Any errors that occur during encoding are fatal.
86-
*
87-
* @param writer The serialized output will be written to the provided writer.
8892
*/
89-
void EncodeQueryData(nanopb::Writer* writer,
90-
const QueryData& query_data) const;
93+
firestore_client_Target EncodeQueryData(const QueryData& query_data) const;
9194

9295
/**
9396
* @brief Decodes nanopb proto representing a ::firestore::proto::Target proto
@@ -110,10 +113,11 @@ class LocalSerializer {
110113
* serializer for Documents in that it preserves the updateTime, which is
111114
* considered an output only value by the server.
112115
*/
113-
void EncodeDocument(nanopb::Writer* writer, const model::Document& doc) const;
116+
google_firestore_v1beta1_Document EncodeDocument(
117+
const model::Document& doc) const;
114118

115-
void EncodeNoDocument(nanopb::Writer* writer,
116-
const model::NoDocument& no_doc) const;
119+
firestore_client_NoDocument EncodeNoDocument(
120+
const model::NoDocument& no_doc) const;
117121

118122
std::unique_ptr<model::NoDocument> DecodeNoDocument(
119123
nanopb::Reader* reader, const firestore_client_NoDocument& proto) const;

0 commit comments

Comments
 (0)