@@ -39,16 +39,72 @@ void EncodeObject(pb_ostream_t* stream,
3939std::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
81137void 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
93149bool 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
110166int64_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