diff options
author | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2013-08-08 20:37:59 +0300 |
---|---|---|
committer | Petteri Aimonen <jpa@git.mail.kapsi.fi> | 2013-08-08 20:42:46 +0300 |
commit | f15093e8bde18bb9fc6f56a7f6fff727eef74e6c (patch) | |
tree | 34d576d792bb2aa3f33676eafe4a29c37c2e5cc3 | |
parent | b663909fb6e86f0ae0f450523e72fb7fbfb719ab (diff) |
Document field extensions support
Update issue 17
Status: FixedInGit
-rw-r--r-- | docs/concepts.rst | 44 | ||||
-rw-r--r-- | docs/index.rst | 2 | ||||
-rw-r--r-- | docs/reference.rst | 35 |
3 files changed, 80 insertions, 1 deletions
diff --git a/docs/concepts.rst b/docs/concepts.rst index 2ae7652..0df5ad6 100644 --- a/docs/concepts.rst +++ b/docs/concepts.rst @@ -256,6 +256,50 @@ generates this field description array for the structure *Person_PhoneNumber*:: }; +Extension fields +================ +Protocol Buffers supports a concept of `extension fields`_, which are +additional fields to a message, but defined outside the actual message. +The definition can even be in a completely separate .proto file. + +The base message is declared as extensible by keyword *extensions* in +the .proto file:: + + message MyMessage { + .. fields .. + extensions 100 to 199; + } + +For each extensible message, *nanopb_generator.py* declares an additional +callback field called *extensions*. The field and associated datatype +*pb_extension_t* forms a linked list of handlers. When an unknown field is +encountered, the decoder calls each handler in turn until either one of them +handles the field, or the list is exhausted. + +The actual extensions are declared using the *extend* keyword in the .proto, +and are in the global namespace:: + + extend MyMessage { + optional int32 myextension = 100; + } + +For each extension, *nanopb_generator.py* creates a constant of type +*pb_extension_type_t*. To link together the base message and the extension, +you have to: + +1. Allocate storage for your field, matching the datatype in the .proto. + For example, for a *int32* field, you need a *int32_t* variable to store + the value. +2. Create a *pb_extension_t* constant, with pointers to your variable and + to the generated *pb_extension_type_t*. +3. Set the *message.extensions* pointer to point to the *pb_extension_t*. + +An example of this is available in *tests/test_encode_extensions.c* and +*tests/test_decode_extensions.c*. + +.. _`extension fields`: https://developers.google.com/protocol-buffers/docs/proto#extensions + + Return values and error handling ================================ diff --git a/docs/index.rst b/docs/index.rst index cb7a201..e56ff4c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -41,7 +41,7 @@ Features and limitations #) Allows specifying maximum size for strings and arrays, so that they can be allocated statically. #) No malloc needed: everything can be allocated statically or on the stack. #) You can use either encoder or decoder alone to cut the code size in half. -#) Support for most protobuf features, including: all data types, nested submessages, default values, repeated and optional fields, packed arrays. +#) Support for most protobuf features, including: all data types, nested submessages, default values, repeated and optional fields, packed arrays, extension fields. #) Callback mechanism for handling messages larger than can fit in available RAM. #) Extensive set of tests. diff --git a/docs/reference.rst b/docs/reference.rst index 6c38f6b..51556d3 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -304,6 +304,41 @@ Protocol Buffers wire types. These are used with `pb_encode_tag`_. :: PB_WT_32BIT = 5 } pb_wire_type_t; +pb_extension_type_t +------------------- +Defines the handler functions and auxiliary data for a field that extends +another message. Usually autogenerated by *nanopb_generator.py*:: + + typedef struct { + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + const void *arg; + } pb_extension_type_t; + +In the normal case, the function pointers are *NULL* and the decoder and +encoder use their internal implementations. The internal implementations +assume that *arg* points to a *pb_field_t* that describes the field in question. + +To implement custom processing of unknown fields, you can provide pointers +to your own functions. Their functionality is mostly the same as for normal +callback fields, except that they get called for any unknown field when decoding. + +pb_extension_t +-------------- +Ties together the extension field type and the storage for the field value:: + + typedef struct { + const pb_extension_type_t *type; + void *dest; + pb_extension_t *next; + } pb_extension_t; + +:type: Pointer to the structure that defines the callback functions. +:dest: Pointer to the variable that stores the field value + (as used by the default extension callback functions.) +:next: Pointer to the next extension handler, or *NULL*. + PB_GET_ERROR ------------ Get the current error message from a stream, or a placeholder string if |