Skip to content

Commit 0d3adb1

Browse files
authored
Partial wrapping of pb_ostream_t (pt1) (firebase#899)
Wraps the varint based encode methods.
1 parent ca3bae5 commit 0d3adb1

File tree

1 file changed

+89
-43
lines changed

1 file changed

+89
-43
lines changed

Firestore/core/src/firebase/firestore/remote/serializer.cc

Lines changed: 89 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,72 @@ void EncodeObject(pb_ostream_t* stream,
3939
std::map<std::string, FieldValue> DecodeObject(pb_istream_t* stream);
4040

4141
/**
42-
* Note that (despite the value parameter type) this works for bool, enum,
43-
* int32, int64, uint32 and uint64 proto field types.
44-
*
45-
* Note: This is not expected to be called direclty, but rather only via the
46-
* other Encode* methods (i.e. EncodeBool, EncodeLong, etc)
47-
*
48-
* @param value The value to encode, represented as a uint64_t.
42+
* Docs TODO(rsgowman). But currently, this just wraps the underlying nanopb
43+
* pb_ostream_t. Eventually, this might use static factory methods to create the
44+
* underlying pb_ostream_t rather than directly passing it in.
4945
*/
50-
void EncodeVarint(pb_ostream_t* stream, uint64_t value) {
51-
bool status = pb_encode_varint(stream, value);
46+
// TODO(rsgowman): Encode* -> Write*
47+
class Writer {
48+
public:
49+
explicit Writer(pb_ostream_t* stream) : stream_(stream) {
50+
}
51+
52+
/**
53+
* Encodes a message type to the output stream.
54+
*
55+
* This essentially wraps calls to nanopb's pb_encode_tag() method.
56+
*
57+
* @param field_number is one of the field tags that nanopb generates based
58+
* off of the proto messages. They're typically named in the format:
59+
* <parentNameSpace>_<childNameSpace>_<message>_<field>_tag, e.g.
60+
* google_firestore_v1beta1_Document_name_tag.
61+
*/
62+
void EncodeTag(pb_wire_type_t wiretype, uint32_t field_number);
63+
64+
void EncodeSize(size_t size);
65+
void EncodeNull();
66+
void EncodeBool(bool bool_value);
67+
void EncodeInteger(int64_t integer_value);
68+
69+
private:
70+
/**
71+
* Encodes a "varint" to the output stream.
72+
*
73+
* This essentially wraps calls to nanopb's pb_encode_varint() method.
74+
*
75+
* Note that (despite the value parameter type) this works for bool, enum,
76+
* int32, int64, uint32 and uint64 proto field types.
77+
*
78+
* Note: This is not expected to be called directly, but rather only
79+
* via the other Encode* methods (i.e. EncodeBool, EncodeLong, etc)
80+
*
81+
* @param value The value to encode, represented as a uint64_t.
82+
*/
83+
void EncodeVarint(uint64_t value);
84+
85+
pb_ostream_t* stream_;
86+
};
87+
88+
// TODO(rsgowman): I've left the methods as near as possible to where they were
89+
// before, which implies that the Writer methods are interspersed with the
90+
// PbIstream methods (or what will become the PbIstream methods). This should
91+
// make it a bit easier to review. Refactor these to group the related methods
92+
// together (probably within their own file rather than here).
93+
94+
void Writer::EncodeTag(pb_wire_type_t wiretype, uint32_t field_number) {
95+
bool status = pb_encode_tag(stream_, wiretype, field_number);
96+
if (!status) {
97+
// TODO(rsgowman): figure out error handling
98+
abort();
99+
}
100+
}
101+
102+
void Writer::EncodeSize(size_t size) {
103+
return EncodeVarint(size);
104+
}
105+
106+
void Writer::EncodeVarint(uint64_t value) {
107+
bool status = pb_encode_varint(stream_, value);
52108
if (!status) {
53109
// TODO(rsgowman): figure out error handling
54110
abort();
@@ -74,8 +130,8 @@ uint64_t DecodeVarint(pb_istream_t* stream) {
74130
return varint_value;
75131
}
76132

77-
void EncodeNull(pb_ostream_t* stream) {
78-
return EncodeVarint(stream, google_protobuf_NullValue_NULL_VALUE);
133+
void Writer::EncodeNull() {
134+
return EncodeVarint(google_protobuf_NullValue_NULL_VALUE);
79135
}
80136

81137
void DecodeNull(pb_istream_t* stream) {
@@ -86,8 +142,8 @@ void DecodeNull(pb_istream_t* stream) {
86142
}
87143
}
88144

89-
void EncodeBool(pb_ostream_t* stream, bool bool_value) {
90-
return EncodeVarint(stream, bool_value);
145+
void Writer::EncodeBool(bool bool_value) {
146+
return EncodeVarint(bool_value);
91147
}
92148

93149
bool DecodeBool(pb_istream_t* stream) {
@@ -103,8 +159,8 @@ bool DecodeBool(pb_istream_t* stream) {
103159
}
104160
}
105161

106-
void EncodeInteger(pb_ostream_t* stream, int64_t integer_value) {
107-
return EncodeVarint(stream, integer_value);
162+
void Writer::EncodeInteger(int64_t integer_value) {
163+
return EncodeVarint(integer_value);
108164
}
109165

110166
int64_t DecodeInteger(pb_istream_t* stream) {
@@ -156,59 +212,49 @@ std::string DecodeString(pb_istream_t* stream) {
156212
// TODO(rsgowman): Refactor to use a helper class that wraps the stream struct.
157213
// This will help with error handling, and should eliminate the issue of two
158214
// 'EncodeFieldValue' methods.
159-
void EncodeFieldValueImpl(pb_ostream_t* stream, const FieldValue& field_value) {
215+
void EncodeFieldValueImpl(pb_ostream_t* raw_stream,
216+
const FieldValue& field_value) {
160217
// TODO(rsgowman): some refactoring is in order... but will wait until after a
161218
// non-varint, non-fixed-size (i.e. string) type is present before doing so.
219+
Writer stream(raw_stream);
162220
bool status = false;
163221
switch (field_value.type()) {
164222
case FieldValue::Type::Null:
165-
status = pb_encode_tag(stream, PB_WT_VARINT,
166-
google_firestore_v1beta1_Value_null_value_tag);
167-
if (!status) {
168-
// TODO(rsgowman): figure out error handling
169-
abort();
170-
}
171-
EncodeNull(stream);
223+
stream.EncodeTag(PB_WT_VARINT,
224+
google_firestore_v1beta1_Value_null_value_tag);
225+
stream.EncodeNull();
172226
break;
173227

174228
case FieldValue::Type::Boolean:
175-
status = pb_encode_tag(stream, PB_WT_VARINT,
176-
google_firestore_v1beta1_Value_boolean_value_tag);
177-
if (!status) {
178-
// TODO(rsgowman): figure out error handling
179-
abort();
180-
}
181-
EncodeBool(stream, field_value.boolean_value());
229+
stream.EncodeTag(PB_WT_VARINT,
230+
google_firestore_v1beta1_Value_boolean_value_tag);
231+
stream.EncodeBool(field_value.boolean_value());
182232
break;
183233

184234
case FieldValue::Type::Integer:
185-
status = pb_encode_tag(stream, PB_WT_VARINT,
186-
google_firestore_v1beta1_Value_integer_value_tag);
187-
if (!status) {
188-
// TODO(rsgowman): figure out error handling
189-
abort();
190-
}
191-
EncodeInteger(stream, field_value.integer_value());
235+
stream.EncodeTag(PB_WT_VARINT,
236+
google_firestore_v1beta1_Value_integer_value_tag);
237+
stream.EncodeInteger(field_value.integer_value());
192238
break;
193239

194240
case FieldValue::Type::String:
195-
status = pb_encode_tag(stream, PB_WT_STRING,
241+
status = pb_encode_tag(raw_stream, PB_WT_STRING,
196242
google_firestore_v1beta1_Value_string_value_tag);
197243
if (!status) {
198244
// TODO(rsgowman): figure out error handling
199245
abort();
200246
}
201-
EncodeString(stream, field_value.string_value());
247+
EncodeString(raw_stream, field_value.string_value());
202248
break;
203249

204250
case FieldValue::Type::Object:
205-
status = pb_encode_tag(stream, PB_WT_STRING,
251+
status = pb_encode_tag(raw_stream, PB_WT_STRING,
206252
google_firestore_v1beta1_Value_map_value_tag);
207253
if (!status) {
208254
// TODO(rsgowman): figure out error handling
209255
abort();
210256
}
211-
EncodeObject(stream, field_value.object_value());
257+
EncodeObject(raw_stream, field_value.object_value());
212258
break;
213259

214260
default:
@@ -291,7 +337,7 @@ void EncodeNestedFieldValue(pb_ostream_t* stream,
291337
size_t size = substream.bytes_written;
292338

293339
// Write out the size to the output stream.
294-
EncodeVarint(stream, size);
340+
Writer(stream).EncodeSize(size);
295341

296342
// If stream is itself a sizing stream, then we don't need to actually parse
297343
// field_value a second time; just update the bytes_written via a call to
@@ -452,7 +498,7 @@ void EncodeObject(pb_ostream_t* stream,
452498
EncodeFieldsEntry(&sizing_stream, kv);
453499
size_t size = sizing_stream.bytes_written;
454500
// Write out the size to the output stream.
455-
EncodeVarint(stream, size);
501+
Writer(stream).EncodeSize(size);
456502

457503
EncodeFieldsEntry(stream, kv);
458504
}

0 commit comments

Comments
 (0)