unittests (some)
[apps/agl-service-can-low-level.git] / pb_decode.c
1 /* pb_decode.c -- decode a protobuf using minimal resources
2  *
3  * 2011 Petteri Aimonen <jpa@kapsi.fi>
4  */
5
6 #include "pb.h"
7 #include "pb_decode.h"
8 #include <string.h>
9
10 const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
11     (pb_decoder_t)&pb_dec_varint,
12     (pb_decoder_t)&pb_dec_svarint,
13     (pb_decoder_t)&pb_dec_fixed,
14     
15     (pb_decoder_t)&pb_dec_bytes,
16     (pb_decoder_t)&pb_dec_string,
17     (pb_decoder_t)&pb_dec_submessage
18 };
19
20 /**************
21  * pb_istream *
22  **************/
23
24 bool pb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
25 {
26     if (stream->bytes_left < count)
27         return false;
28     
29     if (!stream->callback(stream, buf, count))
30         return false;
31     
32     stream->bytes_left -= count;
33     return true;
34 }
35
36 static bool buf_read(pb_istream_t *stream, uint8_t *buf, size_t count)
37 {
38     uint8_t *source = (uint8_t*)stream->state;
39     
40     if (buf != NULL)
41         memcpy(buf, source, count);
42     
43     stream->state = source + count;
44     return true;
45 }
46
47 pb_istream_t pb_istream_from_buffer(uint8_t *buf, size_t bufsize)
48 {
49     pb_istream_t stream;
50     stream.callback = &buf_read;
51     stream.state = buf;
52     stream.bytes_left = bufsize;
53     return stream;
54 }
55
56 /********************
57  * Helper functions *
58  ********************/
59
60 bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest)
61 {
62     uint64_t temp;
63     bool status = pb_decode_varint64(stream, &temp);
64     *dest = temp;
65     return status;
66 }
67
68 bool pb_decode_varint64(pb_istream_t *stream, uint64_t *dest)
69 {
70     uint8_t byte;
71     int bitpos = 0;
72     *dest = 0;
73     
74     while (bitpos < 64 && pb_read(stream, &byte, 1))
75     {
76         *dest |= (uint64_t)(byte & 0x7F) << bitpos;
77         bitpos += 7;
78         
79         if (!(byte & 0x80))
80             return true;
81     }
82     
83     return false;
84 }
85
86 bool pb_skip_varint(pb_istream_t *stream)
87 {
88     uint8_t byte;
89     do
90     {
91         if (!pb_read(stream, &byte, 1))
92             return false;
93     } while (byte & 0x80);
94     return true;
95 }
96
97 bool pb_skip_string(pb_istream_t *stream)
98 {
99     uint32_t length;
100     if (!pb_decode_varint32(stream, &length))
101         return false;
102     
103     return pb_read(stream, NULL, length);
104 }
105
106 /* Currently all wire type related stuff is kept hidden from
107  * callbacks. They shouldn't need it. It's better for performance
108  * to just assume the correct type and fail safely on corrupt message.
109  */
110
111 enum wire_type_t {
112     WT_VARINT = 0,
113     WT_64BIT  = 1,
114     WT_STRING = 2,
115     WT_32BIT  = 5
116 };
117
118 static bool skip(pb_istream_t *stream, int wire_type)
119 {
120     switch (wire_type)
121     {
122         case WT_VARINT: return pb_skip_varint(stream);
123         case WT_64BIT: return pb_read(stream, NULL, 8);
124         case WT_STRING: return pb_skip_string(stream);
125         case WT_32BIT: return pb_read(stream, NULL, 4);
126         default: return false;
127     }
128 }
129
130 /* Read a raw value to buffer, for the purpose of passing it to callback.
131  * Size is maximum size on call, and actual size on return. */
132 static bool read_raw_value(pb_istream_t *stream, int wire_type, uint8_t *buf, size_t *size)
133 {
134     size_t max_size = *size;
135     switch (wire_type)
136     {
137         case WT_VARINT:
138             *size = 0;
139             do
140             {
141                 (*size)++;
142                 if (*size > max_size) return false;
143                 if (!pb_read(stream, buf, 1)) return false;
144             } while (*buf++ & 0x80);
145             return true;
146             
147         case WT_64BIT:
148             *size = 8;
149             return pb_read(stream, buf, 8);
150         
151         case WT_32BIT:
152             *size = 4;
153             return pb_read(stream, buf, 4);
154         
155         default: return false;
156     }
157 }
158
159 /* Decode string length from stream and return a substream with limited length */
160 static bool make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
161 {
162     uint32_t size;
163     if (!pb_decode_varint32(stream, &size))
164         return false;
165     
166     *substream = *stream;
167     if (substream->bytes_left < size)
168         return false;
169     
170     substream->bytes_left = size;
171     stream->bytes_left -= size;
172     return true;
173 }
174
175 /* Iterator for pb_field_t list */
176 typedef struct {
177     const pb_field_t *start;
178     const pb_field_t *current;
179     int field_index;
180     void *dest_struct;
181     void *pData;
182     void *pSize;
183 } pb_field_iterator_t;
184
185 static void pb_field_init(pb_field_iterator_t *iter, const pb_field_t *fields, void *dest_struct)
186 {
187     iter->start = iter->current = fields;
188     iter->field_index = 0;
189     iter->pData = dest_struct;
190     iter->dest_struct = dest_struct;
191 }
192
193 static bool pb_field_next(pb_field_iterator_t *iter)
194 {
195     bool notwrapped = true;
196     iter->current++;
197     iter->field_index++;
198     if (iter->current->tag == 0)
199     {
200         iter->current = iter->start;
201         iter->field_index = 0;
202         iter->pData = iter->dest_struct;
203         notwrapped = false;
204     }
205     
206     iter->pData = (char*)iter->pData + iter->current->data_offset;
207     iter->pSize = (char*)iter->pData + iter->current->size_offset;
208     return notwrapped;
209 }
210
211 static bool pb_field_find(pb_field_iterator_t *iter, int tag)
212 {
213     int start = iter->field_index;
214     
215     do {
216         if (iter->current->tag == tag)
217             return true;
218         pb_field_next(iter);
219     } while (iter->field_index != start);
220     
221     return false;
222 }
223
224 /*************************
225  * Decode a single field *
226  *************************/
227
228 bool decode_field(pb_istream_t *stream, int wire_type, pb_field_iterator_t *iter)
229 {
230     pb_decoder_t func = PB_DECODERS[PB_LTYPE(iter->current->type)];
231     
232     switch (PB_HTYPE(iter->current->type))
233     {
234         case PB_HTYPE_REQUIRED:
235             return func(stream, iter->current, iter->pData);
236             
237         case PB_HTYPE_OPTIONAL:
238             *(bool*)iter->pSize = true;
239             return func(stream, iter->current, iter->pData);
240     
241         case PB_HTYPE_ARRAY:
242             if (wire_type == WT_STRING
243                 && PB_LTYPE(iter->current->type) <= PB_LTYPE_LAST_PACKABLE)
244             {
245                 /* Packed array */
246                 size_t *size = (size_t*)iter->pSize;
247                 pb_istream_t substream;
248                 if (!make_string_substream(stream, &substream))
249                     return false;
250                 
251                 while (substream.bytes_left && *size < iter->current->array_size)
252                 {
253                     void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size);
254                     if (!func(stream, iter->current, pItem))
255                         return false;
256                     (*size)++;
257                 }
258                 return (substream.bytes_left == 0);
259             }
260             else
261             {
262                 /* Repeated field */
263                 size_t *size = (size_t*)iter->pSize;
264                 void *pItem = (uint8_t*)iter->pData + iter->current->data_size * (*size);
265                 if (*size >= iter->current->array_size)
266                     return false;
267                 
268                 (*size)++;
269                 return func(stream, iter->current, pItem);
270             }
271         
272         case PB_HTYPE_CALLBACK:
273             if (wire_type == WT_STRING)
274             {
275                 pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
276                 pb_istream_t substream;
277                 
278                 if (!make_string_substream(stream, &substream))
279                     return false;
280                 
281                 while (substream.bytes_left)
282                 {
283                     if (!pCallback->funcs.decode(&substream, iter->current, pCallback->arg))
284                         return false;
285                 }
286                 return true;
287             }
288             else
289             {
290                 /* Copy the single scalar value to stack.
291                  * This is required so that we can limit the stream length,
292                  * which in turn allows to use same callback for packed and
293                  * not-packed fields. */
294                 pb_istream_t substream;
295                 pb_callback_t *pCallback = (pb_callback_t*)iter->pData;
296                 uint8_t buffer[10];
297                 size_t size = sizeof(buffer);
298                 
299                 if (!read_raw_value(stream, wire_type, buffer, &size))
300                     return false;
301                 substream = pb_istream_from_buffer(buffer, size);
302                 
303                 return pCallback->funcs.decode(&substream, iter->current, pCallback->arg);
304             }
305             
306         default:
307             return false;
308     }
309 }
310
311 /*********************
312  * Decode all fields *
313  *********************/
314
315 bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
316 {
317     uint32_t fields_seen = 0; /* Used to check for required fields */
318     pb_field_iterator_t iter;
319     int i;
320     
321     if (fields[0].tag == 0)
322     {
323         /* No fields -> nothing to do */
324         return pb_read(stream, NULL, stream->bytes_left);
325     }
326     
327     pb_field_init(&iter, fields, dest_struct);
328     
329     /* Initialize size/has fields and apply default values */
330     do
331     {
332         if (PB_HTYPE(iter.current->type) == PB_HTYPE_OPTIONAL)
333         {
334             *(bool*)iter.pSize = false;
335             
336             /* Initialize to default value */
337             if (iter.current->ptr != NULL)
338                 memcpy(iter.pData, iter.current->ptr, iter.current->data_size);
339             else
340                 memset(iter.pData, 0, iter.current->data_size);
341         }
342         else if (PB_HTYPE(iter.current->type) == PB_HTYPE_ARRAY)
343         {
344             *(size_t*)iter.pSize = 0;
345         }
346     } while (pb_field_next(&iter));
347     
348     while (stream->bytes_left)
349     {
350         uint32_t temp;
351         int tag, wire_type;
352         if (!pb_decode_varint32(stream, &temp))
353             return false;
354         
355         tag = temp >> 3;
356         wire_type = temp & 7;
357         
358         if (!pb_field_find(&iter, tag))
359         {
360             /* No match found, skip data */
361             skip(stream, wire_type);
362             continue;
363         }
364         
365         fields_seen |= 1 << (iter.field_index & 31);
366             
367         if (!decode_field(stream, wire_type, &iter))
368             return false;
369     }
370     
371     /* Check that all required fields (mod 31) were present. */
372     for (i = 0; fields[i].tag != 0; i++)
373     {
374         if (PB_HTYPE(fields[i].type) == PB_HTYPE_REQUIRED &&
375             !(fields_seen & (1 << (i & 31))))
376         {
377             return false;
378         }
379     }
380     
381     return true;
382 }
383
384 /* Field decoders */
385
386 /* Copy destsize bytes from src so that values are casted properly.
387  * On little endian machine, copy first n bytes of src
388  * On big endian machine, copy last n bytes of src
389  * srcsize must always be larger than destsize
390  */
391 static void endian_copy(void *dest, void *src, size_t destsize, size_t srcsize)
392 {
393 #ifdef __BIG_ENDIAN__
394     memcpy(dest, (char*)src + (srcsize - destsize), destsize);
395 #else
396     memcpy(dest, src, destsize);
397 #endif
398 }
399
400 bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
401 {
402     uint64_t temp;
403     bool status = pb_decode_varint64(stream, &temp);
404     endian_copy(dest, &temp, field->data_size, sizeof(temp));
405     return status;
406 }
407
408 bool pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
409 {
410     uint64_t temp;
411     bool status = pb_decode_varint64(stream, &temp);
412     temp = (temp >> 1) ^ -(int64_t)(temp & 1);
413     endian_copy(dest, &temp, field->data_size, sizeof(temp));
414     return status;
415 }
416
417 bool pb_dec_fixed(pb_istream_t *stream, const pb_field_t *field, void *dest)
418 {
419 #ifdef __BIG_ENDIAN__
420     uint8_t bytes[8] = {0};
421     bool status = pb_read(stream, bytes, field->data_size);
422     uint8_t lebytes[8] = {bytes[7], bytes[6], bytes[5], bytes[4], 
423                           bytes[3], bytes[2], bytes[1], bytes[0]};
424     endian_copy(dest, lebytes, field->data_size, 8);
425     return status;
426 #else
427     return pb_read(stream, (uint8_t*)dest, field->data_size);
428 #endif
429 }
430
431 bool pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, uint8_t *dest)
432 {
433     pb_bytes_array_t *x = (pb_bytes_array_t*)dest;
434     
435     uint32_t temp;
436     if (!pb_decode_varint32(stream, &temp))
437         return false;
438     x->size = temp;
439     
440     /* Note: data_size includes the size of the x.size field, too.
441      * Calculate actual size starting from offset. */
442     if (x->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
443         return false;
444     
445     return pb_read(stream, x->bytes, x->size);
446 }
447
448 bool pb_dec_string(pb_istream_t *stream, const pb_field_t *field, uint8_t *dest)
449 {
450     uint32_t size;
451     bool status;
452     if (!pb_decode_varint32(stream, &size))
453         return false;
454     
455     if (size > field->data_size - 1)
456         return false;
457     
458     status = pb_read(stream, (uint8_t*)dest, size);
459     *((uint8_t*)dest + size) = 0;
460     return status;
461 }
462
463 bool pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
464 {
465     pb_istream_t substream;
466     
467     if (!make_string_substream(stream, &substream))
468         return false;
469     
470     if (field->ptr == NULL)
471         return false;
472     
473     return pb_decode(&substream, (pb_field_t*)field->ptr, dest);
474 }