1 /* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c.
2  * The main function is pb_encode. You also need an output stream, and the
3  * field descriptions created by nanopb_generator.py.
4  */
5 
6 #ifndef PB_ENCODE_H_INCLUDED
7 #define PB_ENCODE_H_INCLUDED
8 
9 #include "pb.h"
10 
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14 
15 /* Structure for defining custom output streams. You will need to provide
16  * a callback function to write the bytes to your storage, which can be
17  * for example a file or a network socket.
18  *
19  * The callback must conform to these rules:
20  *
21  * 1) Return false on IO errors. This will cause encoding to abort.
22  * 2) You can use state to store your own data (e.g. buffer pointer).
23  * 3) pb_write will update bytes_written after your callback runs.
24  * 4) Substreams will modify max_size and bytes_written. Don't use them
25  *    to calculate any pointers.
26  */
27 struct pb_ostream_s {
28 #ifdef PB_BUFFER_ONLY
29   /* Callback pointer is not used in buffer-only configuration.
30    * Having an int pointer here allows binary compatibility but
31    * gives an error if someone tries to assign callback function.
32    * Also, NULL pointer marks a 'sizing stream' that does not
33    * write anything.
34    */
35   int *callback;
36 #else
37   bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
38 #endif
39   void *state;     /* Free field for use by callback implementation. */
40   size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */
41   size_t bytes_written; /* Number of bytes written so far. */
42 
43 #ifndef PB_NO_ERRMSG
44   const char *errmsg;
45 #endif
46 };
47 
48 /***************************
49  * Main encoding functions *
50  ***************************/
51 
52 /* Encode a single protocol buffers message from C structure into a stream.
53  * Returns true on success, false on any failure.
54  * The actual struct pointed to by src_struct must match the description in
55  * fields. All required fields in the struct are assumed to have been filled in.
56  *
57  * Example usage:
58  *    MyMessage msg = {};
59  *    uint8_t buffer[64];
60  *    pb_ostream_t stream;
61  *
62  *    msg.field1 = 42;
63  *    stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
64  *    pb_encode(&stream, MyMessage_fields, &msg);
65  */
66 bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[],
67                const void *src_struct);
68 
69 /* Same as pb_encode, but prepends the length of the message as a varint.
70  * Corresponds to writeDelimitedTo() in Google's protobuf API.
71  */
72 bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[],
73                          const void *src_struct);
74 
75 /* Same as pb_encode, but appends a null byte to the message for termination.
76  * NOTE: This behaviour is not supported in most other protobuf implementations,
77  * so pb_encode_delimited() is a better option for compatibility.
78  */
79 bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[],
80                               const void *src_struct);
81 
82 /* Encode the message to get the size of the encoded data, but do not store
83  * the data. */
84 bool pb_get_encoded_size(size_t *size, const pb_field_t fields[],
85                          const void *src_struct);
86 
87 /**************************************
88  * Functions for manipulating streams *
89  **************************************/
90 
91 /* Create an output stream for writing into a memory buffer.
92  * The number of bytes written can be found in stream.bytes_written after
93  * encoding the message.
94  *
95  * Alternatively, you can use a custom stream that writes directly to e.g.
96  * a file or a network socket.
97  */
98 pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize);
99 
100 /* Pseudo-stream for measuring the size of a message without actually storing
101  * the encoded data.
102  *
103  * Example usage:
104  *    MyMessage msg = {};
105  *    pb_ostream_t stream = PB_OSTREAM_SIZING;
106  *    pb_encode(&stream, MyMessage_fields, &msg);
107  *    printf("Message size is %d\n", stream.bytes_written);
108  */
109 #ifndef PB_NO_ERRMSG
110 #define PB_OSTREAM_SIZING \
111   { 0, 0, 0, 0, 0 }
112 #else
113 #define PB_OSTREAM_SIZING \
114   { 0, 0, 0, 0 }
115 #endif
116 
117 /* Function to write into a pb_ostream_t stream. You can use this if you need
118  * to append or prepend some custom headers to the message.
119  */
120 bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
121 
122 /************************************************
123  * Helper functions for writing field callbacks *
124  ************************************************/
125 
126 /* Encode field header based on type and field number defined in the field
127  * structure. Call this from the callback before writing out field contents. */
128 bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field);
129 
130 /* Encode field header by manually specifying wire type. You need to use this
131  * if you want to write out packed arrays from a callback field. */
132 bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype,
133                    uint32_t field_number);
134 
135 /* Encode an integer in the varint format.
136  * This works for bool, enum, int32, int64, uint32 and uint64 field types. */
137 #ifndef PB_WITHOUT_64BIT
138 bool pb_encode_varint(pb_ostream_t *stream, uint64_t value);
139 #else
140 bool pb_encode_varint(pb_ostream_t *stream, uint32_t value);
141 #endif
142 
143 /* Encode an integer in the zig-zagged svarint format.
144  * This works for sint32 and sint64. */
145 #ifndef PB_WITHOUT_64BIT
146 bool pb_encode_svarint(pb_ostream_t *stream, int64_t value);
147 #else
148 bool pb_encode_svarint(pb_ostream_t *stream, int32_t value);
149 #endif
150 
151 /* Encode a string or bytes type field. For strings, pass strlen(s) as size. */
152 bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer,
153                       size_t size);
154 
155 /* Encode a fixed32, sfixed32 or float value.
156  * You need to pass a pointer to a 4-byte wide C variable. */
157 bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);
158 
159 #ifndef PB_WITHOUT_64BIT
160 /* Encode a fixed64, sfixed64 or double value.
161  * You need to pass a pointer to a 8-byte wide C variable. */
162 bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);
163 #endif
164 
165 /* Encode a submessage field.
166  * You need to pass the pb_field_t array and pointer to struct, just like
167  * with pb_encode(). This internally encodes the submessage twice, first to
168  * calculate message size and then to actually write it out.
169  */
170 bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[],
171                           const void *src_struct);
172 
173 #ifdef __cplusplus
174 } /* extern "C" */
175 #endif
176 
177 #endif
178