+/* Iterator for pb_field_t list */
+typedef struct {
+ const pb_field_t *start;
+ const pb_field_t *current;
+ int field_index;
+ void *dest_struct;
+ void *pData;
+ void *pSize;
+} pb_field_iterator_t;
+
+static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, void *dest_struct)
+{
+ iter->start = iter->current = fields;
+ iter->field_index = 0;
+ iter->pData = (char*)dest_struct + iter->current->data_offset;
+ iter->pSize = (char*)iter->pData + iter->current->size_offset;
+ iter->dest_struct = dest_struct;
+}
+
+static bool pb_field_next(pb_field_iterator_t *iter)
+{
+ bool notwrapped = true;
+ size_t prev_size = iter->current->data_size;
+
+ if (PB_HTYPE(iter->current->type) == PB_HTYPE_ARRAY)
+ prev_size *= iter->current->array_size;
+
+ iter->current++;
+ iter->field_index++;
+ if (iter->current->tag == 0)
+ {
+ iter->current = iter->start;
+ iter->field_index = 0;
+ iter->pData = iter->dest_struct;
+ prev_size = 0;
+ notwrapped = false;
+ }
+
+ iter->pData = (char*)iter->pData + prev_size + iter->current->data_offset;
+ iter->pSize = (char*)iter->pData + iter->current->size_offset;
+ return notwrapped;
+}
+
+static bool checkreturn pb_field_find(pb_field_iterator_t *iter, int tag)
+{
+ int start = iter->field_index;
+
+ do {
+ if (iter->current->tag == tag)
+ return true;
+ pb_field_next(iter);
+ } while (iter->field_index != start);
+
+ return false;
+}
+
+/*************************
+ * Decode a single field *
+ *************************/
+
+static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iterator_t *iter)