aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-08-08 20:37:59 +0300
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2013-08-08 20:42:46 +0300
commitf15093e8bde18bb9fc6f56a7f6fff727eef74e6c (patch)
tree34d576d792bb2aa3f33676eafe4a29c37c2e5cc3
parentb663909fb6e86f0ae0f450523e72fb7fbfb719ab (diff)
Document field extensions support
Update issue 17 Status: FixedInGit
-rw-r--r--docs/concepts.rst44
-rw-r--r--docs/index.rst2
-rw-r--r--docs/reference.rst35
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