# Nanopb: API reference

## Compilation options

The following options can be specified in one of two ways:

1.  Using the -D switch on the C compiler command line.
2.  Using a `#define` at the top of pb.h.

> **NOTE:** You must have the same settings for the nanopb library and all code that
includes nanopb headers.

* `PB_ENABLE_MALLOC`: Enable dynamic allocation support in the decoder.
* `PB_MAX_REQUIRED_FIELDS`: Maximum number of proto2 `required` fields to check for presence. Default value is 64. Compiler warning will tell if you need this.
* `PB_FIELD_32BIT`: Add support for field tag numbers over 65535, fields larger than 64 kiB and arrays larger than 65535 entries. Compiler warning will tell if you need this.
* `PB_NO_ERRMSG`: Disable error message support to save code size. Only error information is the `true`/`false` return value.
* `PB_BUFFER_ONLY`: Disable support for custom streams. Only supports encoding and decoding with memory buffers. Speeds up execution and slightly decreases code size.
* `PB_SYSTEM_HEADER`: Replace the standards header files with a single system-specific header file. Value must include quotes, for example `#define PB_SYSTEM_HEADER "foo.h"`. See [extra/pb_syshdr.h](https://github.com/nanopb/nanopb/blob/master/extra/pb_syshdr.h) for an example.
* `PB_WITHOUT_64BIT`: Disable support of 64-bit integer fields, for old compilers or for a slight speedup on 8-bit platforms.
* `PB_ENCODE_ARRAYS_UNPACKED`: Encode scalar arrays in the unpacked format, which takes up more space. Only to be used when the decoder on the receiving side cannot process packed arrays, such as [protobuf.js versions before 2020](https://github.com/protocolbuffers/protobuf/issues/1701).
* `PB_CONVERT_DOUBLE_FLOAT`: Convert doubles to floats for platforms that do not support 64-bit `double` datatype. Mainly `AVR` processors.
* `PB_VALIDATE_UTF8`: Check whether incoming strings are valid UTF-8 sequences. Adds a small performance and code size penalty.
* `PB_C99_STATIC_ASSERT`: Use C99 style negative array trick for static assertions. For compilers that do not support C11 standard.
* `PB_NO_STATIC_ASSERT`: Disable static assertions at compile time. Only for compilers with limited support of C standards.

The `PB_MAX_REQUIRED_FIELDS` and `PB_FIELD_32BIT` settings allow
raising some datatype limits to suit larger messages. Their need is
recognized automatically by C-preprocessor `#if`-directives in the
generated `.pb.c` files. The default setting is to use the smallest
datatypes (least resources used).

## Proto file options

The generator behaviour can be adjusted using several options, defined
in the [nanopb.proto](https://github.com/nanopb/nanopb/blob/master/generator/proto/nanopb.proto) file in the generator folder. Here is a list of the most common options, but see the file for a full list:

* `max_size`: Allocated maximum size for `bytes` and `string` fields. For strings, this includes the terminating zero.
* `max_length`: Maximum length for `string` fields. Setting this is equivalent to setting `max_size` to a value of length + 1.
* `max_count`: Allocated maximum number of entries in arrays (`repeated` fields).
* `type`: Select how memory is allocated for the generated field. Default value is `FT_DEFAULT`, which defaults to `FT_STATIC` when possible and `FT_CALLBACK` if not possible. You can use `FT_CALLBACK`, `FT_POINTER`, `FT_STATIC` or `FT_IGNORE` to select a callback field, a dynamically allocate dfield, a statically allocated field or to completely ignore the field.
* `long_names`: Prefix the enum name to the enum value in definitions, i.e. `EnumName_EnumValue`. Enabled by default.
* `packed_struct`: Make the generated structures packed, which saves some RAM space but slows down execution. This can only be used if the CPU supports unaligned access to variables.
* `skip_message`: Skip a whole message from generation. Can be used to remove message types that are not needed in an application.
* `no_unions`: Generate `oneof` fields as multiple optional fields instead of a C `union {}`.
* `anonymous_oneof`: Generate `oneof` fields as an anonymous union.
* `msgid`: Specifies a unique id for this message type. Can be used by user code as an identifier.
* `fixed_length`: Generate `bytes` fields with a constant length defined by `max_size`. A separate `.size` field will then not be generated.
* `fixed_count`: Generate arrays with constant length defined by `max_count`.
* `package`: Package name that applies only for nanopb generator. Defaults to name defined by `package` keyword in .proto file, which applies for all languages.
* `int_size`: Override the integer type of a field. For example, specify `int_size = IS_8` to convert `int32` from protocol definition into `int8_t` in the structure.

These options can be defined for the .proto files before they are
converted using the nanopb-generatory.py. There are three ways to define
the options:

1.  Using a separate .options file. This allows using wildcards for
    applying same options to multiple fields.
2.  Defining the options on the command line of nanopb_generator.py.
    This only makes sense for settings that apply to a whole file.
3.  Defining the options in the .proto file using the nanopb extensions.
    This keeps the options close to the fields they apply to, but can be
    problematic if the same .proto file is shared with many projects.

The effect of the options is the same no matter how they are given. The
most common purpose is to define maximum size for string fields in order
to statically allocate them.

### Defining the options in a .options file

The preferred way to define options is to have a separate file
'myproto.options' in the same directory as the 'myproto.proto'. :

    # myproto.proto
    message MyMessage {
        required string name = 1;
        repeated int32 ids = 4;
    }

    # myproto.options
    MyMessage.name         max_size:40
    MyMessage.ids          max_count:5

The generator will automatically search for this file and read the
options from it. The file format is as follows:

-   Lines starting with `#` or `//` are regarded as comments.
-   Blank lines are ignored.
-   All other lines should start with a field name pattern, followed by
    one or more options. For example: `MyMessage.myfield max_size:5 max_count:10`.
-   The field name pattern is matched against a string of form
    `Message.field`. For nested messages, the string is
    `Message.SubMessage.field`. A whole file can be matched by its
    filename `dir/file.proto`.
-   The field name pattern may use the notation recognized by Python
    fnmatch():
    -   `*` matches any part of string, like `Message.*` for all
        fields
    -   `?` matches any single character
    -   `[seq]` matches any of characters `s`, `e` and `q`
    -   `[!seq]` matches any other character
-   The options are written as `option_name:option_value` and
    several options can be defined on same line, separated by
    whitespace.
-   Options defined later in the file override the ones specified
    earlier, so it makes sense to define wildcard options first in the
    file and more specific ones later.

To debug problems in applying the options, you can use the `-v` option
for the nanopb generator. With protoc, plugin options are specified with
`--nanopb_opt`:

    nanopb_generator -v message.proto           # When invoked directly
    protoc ... --nanopb_opt=-v --nanopb_out=. message.proto  # When invoked through protoc

Protoc doesn't currently pass include path into plugins. Therefore if
your `.proto` is in a subdirectory, nanopb may have trouble finding the
associated `.options` file. A workaround is to specify include path
separately to the nanopb plugin, like:

    protoc -Isubdir --nanopb_opt=-Isubdir --nanopb_out=. message.proto

If preferred, the name of the options file can be set using generator
argument `-f`.

### Defining the options on command line

The nanopb_generator.py has a simple command line option `-s OPTION:VALUE`.
The setting applies to the whole file that is being processed.

### Defining the options in the .proto file

The .proto file format allows defining custom options for the fields.
The nanopb library comes with *nanopb.proto* which does exactly that,
allowing you do define the options directly in the .proto file:

~~~~ protobuf
import "nanopb.proto";

message MyMessage {
    required string name = 1 [(nanopb).max_size = 40];
    repeated int32 ids = 4   [(nanopb).max_count = 5];
}
~~~~

A small complication is that you have to set the include path of protoc
so that nanopb.proto can be found. Therefore, to compile a .proto file
which uses options, use a protoc command similar to:

    protoc -Inanopb/generator/proto -I. --nanopb_out=. message.proto

The options can be defined in file, message and field scopes:

~~~~ protobuf
option (nanopb_fileopt).max_size = 20; // File scope
message Message
{
    option (nanopb_msgopt).max_size = 30; // Message scope
    required string fieldsize = 1 [(nanopb).max_size = 40]; // Field scope
}
~~~~

## pb.h

### pb_byte_t

Type used for storing byte-sized data, such as raw binary input and
bytes-type fields.

    typedef uint_least8_t pb_byte_t;

For most platforms this is equivalent to `uint8_t`. Some platforms
however do not support 8-bit variables, and on those platforms 16 or 32
bits need to be used for each byte.

### pb_size_t

Type used for storing tag numbers and sizes of message fields. By
default the type is 16-bit:

    typedef uint_least16_t pb_size_t;

If tag numbers or fields larger than 65535 are needed, `PB_FIELD_32BIT`
option can be used to change the type to 32-bit value.

### pb_type_t

Type used to store the type of each field, to control the
encoder/decoder behaviour.

    typedef uint_least8_t pb_type_t;

The low-order nibble of the enumeration values defines the function that
can be used for encoding and decoding the field data:

| LTYPE identifier                 |Value  |Storage format
| ---------------------------------|-------|------------------------------------------------
| `PB_LTYPE_BOOL`                  |0x00   |Boolean.
| `PB_LTYPE_VARINT`                |0x01   |Integer.
| `PB_LTYPE_UVARINT`               |0x02   |Unsigned integer.
| `PB_LTYPE_SVARINT`               |0x03   |Integer, zigzag encoded.
| `PB_LTYPE_FIXED32`               |0x04   |32-bit integer or floating point.
| `PB_LTYPE_FIXED64`               |0x05   |64-bit integer or floating point.
| `PB_LTYPE_BYTES`                 |0x06   |Structure with `size_t` field and byte array.
| `PB_LTYPE_STRING`                |0x07   |Null-terminated string.
| `PB_LTYPE_SUBMESSAGE`            |0x08   |Submessage structure.
| `PB_LTYPE_SUBMSG_W_CB`           |0x09   |Submessage with pre-decoding callback.
| `PB_LTYPE_EXTENSION`             |0x0A   |Pointer to `pb_extension_t`.
| `PB_LTYPE_FIXED_LENGTH_BYTES`    |0x0B   |Inline `pb_byte_t` array of fixed size.

The bits 4-5 define whether the field is required, optional or repeated.
There are separate definitions for semantically different modes, even
though some of them share values and are distinguished based on values
of other fields:

 |HTYPE identifier     |Value  |Field handling
 |---------------------|-------|--------------------------------------------------------------------------------------------
 |`PB_HTYPE_REQUIRED`  |0x00   |Verify that field exists in decoded message.
 |`PB_HTYPE_OPTIONAL`  |0x10   |Use separate `has_<field>` boolean to specify whether the field is present.
 |`PB_HTYPE_SINGULAR`  |0x10   |Proto3 field, which is present when its value is non-zero.
 |`PB_HTYPE_REPEATED`  |0x20   |A repeated field with preallocated array. Separate `<field>_count` for number of items.
 |`PB_HTYPE_FIXARRAY`  |0x20   |A repeated field that has constant length.
 |`PB_HTYPE_ONEOF`     |0x30   |Oneof-field, only one of each group can be present.

The bits 6-7 define the how the storage for the field is allocated:

|ATYPE identifier     |Value  |Allocation method
|---------------------|-------|--------------------------------------------------------------------------------------------
|`PB_ATYPE_STATIC`    |0x00   |Statically allocated storage in the structure.
|`PB_ATYPE_POINTER`   |0x80   |Dynamically allocated storage. Struct field contains a pointer to the storage.
|`PB_ATYPE_CALLBACK`  |0x40   |A field with dynamic storage size. Struct field contains a pointer to a callback function.

### pb_msgdesc_t

Autogenerated structure that contains information about a message and
pointers to the field descriptors. Use functions defined in
`pb_common.h` to process the field information.

    typedef struct pb_msgdesc_s pb_msgdesc_t;
    struct pb_msgdesc_s {
        pb_size_t field_count;
        const uint32_t *field_info;
        const pb_msgdesc_t * const * submsg_info;
        const pb_byte_t *default_value;

        bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
    };

|                 |                                                        |
|-----------------|--------------------------------------------------------|
|`field_count`    | Total number of fields in the message.
|`field_info`     | Pointer to compact representation of the field information.
|`submsg_info`    | Pointer to array of pointers to descriptors for submessages.
|`default_value`  | Default values for this message as an encoded protobuf message.
|`field_callback` | Function used to handle all callback fields in this message. By default `pb_default_field_callback()`  which loads per-field callbacks from a `pb_callback_t` structure.

### pb_field_iter_t

Describes a single structure field with memory position in relation to
others. The field information is stored in a compact format and loaded
into `pb_field_iter_t` by the functions defined in `pb_common.h`.

    typedef struct pb_field_iter_s pb_field_iter_t;
    struct pb_field_iter_s {
        const pb_msgdesc_t *descriptor;
        void *message;

        pb_size_t index;
        pb_size_t field_info_index;
        pb_size_t required_field_index;
        pb_size_t submessage_index;

        pb_size_t tag;
        pb_size_t data_size;
        pb_size_t array_size;
        pb_type_t type;

        void *pField;
        void *pData;
        void *pSize;

        const pb_msgdesc_t *submsg_desc;
    };

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| descriptor           | Pointer to `pb_msgdesc_t` for the message that contains this field.
| message              | Pointer to the start of the message structure.
| index                | Index of the field inside the message
| field_info_index     | Index to the internal `field_info` array
| required_field_index | Index that counts only the required fields
| submessage_index     | Index that counts only submessages
| tag                  | Tag number defined in `.proto` file for this field.
| data_size            | `sizeof()` of the field in the structure. For repeated fields this is for a single array entry.
| array_size           | Maximum number of items in a statically allocated array.
| type                 | Type ([pb_type_t](#pb_type_t)) of the field.
| pField               | Pointer to the field storage in the structure.
| pData                | Pointer to data contents. For arrays and pointers this can be different than `pField`.
| pSize                | Pointer to count or has field, or NULL if this field doesn't have such.
| submsg_desc          | For submessage fields, points to the descriptor for the submessage.

By default [pb_size_t](#pb_size_t) is 16-bit, limiting the sizes and
tags to 65535. The limit can be raised by defining `PB_FIELD_32BIT`.

### pb_bytes_array_t

An byte array with a field for storing the length:

    typedef struct {
        pb_size_t size;
        pb_byte_t bytes[1];
    } pb_bytes_array_t;

In an actual array, the length of `bytes` may be different. The macros
`PB_BYTES_ARRAY_T()` and `PB_BYTES_ARRAY_T_ALLOCSIZE()`
are used to allocate variable length storage for bytes fields.

### pb_callback_t

Part of a message structure, for fields with type PB_HTYPE_CALLBACK:

    typedef struct _pb_callback_t pb_callback_t;
    struct _pb_callback_t {
        union {
            bool (*decode)(pb_istream_t *stream, const pb_field_iter_t *field, void **arg);
            bool (*encode)(pb_ostream_t *stream, const pb_field_iter_t *field, void * const *arg);
        } funcs;

        void *arg;
    };

A pointer to the *arg* is passed to the callback when calling. It can be
used to store any information that the callback might need. Note that
this is a double pointer. If you set `field.arg` to point to
`&data` in your main code, in the callback you can access it like this:

    myfunction(*arg);           /* Gives pointer to data as argument */
    myfunction(*(data_t*)*arg); /* Gives value of data as argument */
    *arg = newdata;             /* Alters value of field.arg in structure */

When calling [pb_encode](#pb_encode), `funcs.encode` is used, and
similarly when calling [pb_decode](#pb_decode), `funcs.decode` is used.
The function pointers are stored in the same memory location but are of
incompatible types. You can set the function pointer to NULL to skip the
field.

### pb_wire_type_t

Protocol Buffers wire types. These are used with
[pb_encode_tag](#pb_encode_tag). :

    typedef enum {
        PB_WT_VARINT = 0,
        PB_WT_64BIT  = 1,
        PB_WT_STRING = 2,
        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_iter_t](#pb_field_iter_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. For message structs that have extensions, the generator will
add a `pb_extension_t*` field. It should point to a linked list of
extensions.

    typedef struct {
        const pb_extension_type_t *type;
        void *dest;
        pb_extension_t *next;
        bool found;
    } 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` for last handler.
| found                | Decoder sets this to true if the extension was found.

### PB_GET_ERROR

Get the current error message from a stream, or a placeholder string if
there is no error message:

    #define PB_GET_ERROR(stream) (string expression)

This should be used for printing errors, for example:

    if (!pb_decode(...))
    {
        printf("Decode failed: %s\n", PB_GET_ERROR(stream));
    }

The macro only returns pointers to constant strings (in code memory), so
that there is no need to release the returned pointer.

### PB_RETURN_ERROR

Set the error message and return false:

    #define PB_RETURN_ERROR(stream,msg) (sets error and returns false)

This should be used to handle error conditions inside nanopb functions
and user callback functions:

    if (error_condition)
    {
        PB_RETURN_ERROR(stream, "something went wrong");
    }

The *msg* parameter must be a constant string.

### PB_BIND

This macro generates the [pb_msgdesc_t](#pb_msgdesc_t) and associated
arrays, based on a list of fields in [X-macro](https://en.wikipedia.org/wiki/X_Macro) format. :

    #define PB_BIND(msgname, structname, width) ...

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| msgname              | Name of the message type. Expects `msgname_FIELDLIST` macro to exist.
| structname           | Name of the C structure to bind to.
| width                | Number of words per field descriptor, or `AUTO` to use minimum size possible.

This macro is automatically invoked inside the autogenerated `.pb.c`
files. User code can also call it to bind message types with custom
structures or class types.

## pb_encode.h

### pb_ostream_from_buffer

Constructs an output stream for writing into a memory buffer. It uses an internal callback that
stores the pointer in stream `state` field. :

    pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| buf                  | Memory buffer to write into.
| bufsize              | Maximum number of bytes to write.
| returns              | An output stream.

After writing, you can check `stream.bytes_written` to find out how
much valid data there is in the buffer. This should be passed as the
message length on decoding side.

### pb_write

Writes data to an output stream. Always use this function, instead of
trying to call stream callback manually. :

    bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to.
| buf                  | Pointer to buffer with the data to be written.
| count                | Number of bytes to write.
| returns              | True on success, false if maximum length is exceeded or an IO error happens.

> **NOTE:** If an error happens, *bytes_written* is not incremented. Depending on
the callback used, calling pb_write again after it has failed once may
cause undefined behavior. Nanopb itself never does this, instead it
returns the error to user application. The builtin
`pb_ostream_from_buffer` is safe to call again after failed write.

### pb_encode

Encodes the contents of a structure as a protocol buffers message and
writes it to output stream. :

    bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to.
| fields               | Message descriptor, usually autogenerated.
| src_struct           | Pointer to the message structure. Must match `fields` descriptor.
| returns              | True on success, false on any error condition. Error message is set to `stream->errmsg`.

Normally pb_encode simply walks through the fields description array
and serializes each field in turn. However, submessages must be
serialized twice: first to calculate their size and then to actually
write them to output. This causes some constraints for callback fields,
which must return the same data on every call.

### pb_encode_ex

Encodes the message, with extended behavior set by flags:

    bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to.
| fields               | Message descriptor, usually autogenerated.
| src_struct           | Pointer to the message structure. Must match `fields` descriptor.
| flags                | Extended options, see below.
| returns              | True on success, false on any error condition. Error message is set to `stream->errmsg`.

The options that can be defined are:

* `PB_ENCODE_DELIMITED`: Indicate the length of the message by prefixing with a varint-encoded length. Compatible with `parseDelimitedFrom` in Google's protobuf library.
* `PB_ENCODE_NULLTERMINATED`: Indicate the length of the message by appending a zero tag value after it. Supported by nanopb decoder, but not by most other protobuf libraries.

### pb_get_encoded_size

Calculates the length of the encoded message.

    bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| size                 | Calculated size of the encoded message.
| fields               | Message descriptor, usually autogenerated.
| src_struct           | Pointer to the data that will be serialized.
| returns              | True on success, false on detectable errors in field description or if a field encoder returns false.

### Callback field encoders
The functions with names `pb_encode_<datatype>` are used when dealing with
callback fields. The typical reason for using callbacks is to have an
array of unlimited size. In that case, [pb_encode](#pb_encode) will
call your callback function, which in turn will call `pb_encode_<datatype>`
functions repeatedly to write out values.

The tag of a field must be encoded first with
[pb_encode_tag_for_field](#pb_encode_tag_for_field). After that, you
can call exactly one of the content-writing functions to encode the
payload of the field. For repeated fields, you can repeat this process
multiple times.

Writing packed arrays is a little bit more involved: you need to use
`pb_encode_tag` and specify `PB_WT_STRING` as the wire
type. Then you need to know exactly how much data you are going to
write, and use [pb_encode_varint](#pb_encode_varint) to write out the
number of bytes before writing the actual data. Substreams can be used
to determine the number of bytes beforehand; see
[pb_encode_submessage](#pb_encode_submessage) source code for an
example.

See [Google Protobuf Encoding Format Documentation](https://developers.google.com/protocol-buffers/docs/encoding)
for background information on the Protobuf wire format.

#### pb_encode_tag

Starts a field in the Protocol Buffers binary format: encodes the field
number and the wire type of the data.

    bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to. 1-5 bytes will be written.
| wiretype             | `PB_WT_VARINT`, `PB_WT_64BIT`, `PB_WT_STRING` or `PB_WT_32BIT`
| field_number         | Identifier for the field, defined in the .proto file. You can get it from `field->tag`.
| returns              | True on success, false on IO error.

#### pb_encode_tag_for_field

Same as [pb_encode_tag](#pb_encode_tag), except takes the parameters
from a `pb_field_iter_t` structure.

    bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to. 1-5 bytes will be written.
| field                | Field iterator for this field.
| returns              | True on success, false on IO error or unknown field type.

This function only considers the `PB_LTYPE` of the field. You can use it from
your field callbacks, because the source generator writes correct `LTYPE`
also for callback type fields.

Wire type mapping is as follows:

| LTYPEs                                           | Wire type
|--------------------------------------------------|-----------------
| BOOL, VARINT, UVARINT, SVARINT                   | PB_WT_VARINT
| FIXED64                                          | PB_WT_64BIT
| STRING, BYTES, SUBMESSAGE, FIXED_LENGTH_BYTES    | PB_WT_STRING
| FIXED32                                          | PB_WT_32BIT

#### pb_encode_varint

Encodes a signed or unsigned integer in the
[varint](http://code.google.com/apis/protocolbuffers/docs/encoding.html#varints)
format. Works for fields of type `bool`, `enum`, `int32`, `int64`, `uint32` and `uint64`:

    bool pb_encode_varint(pb_ostream_t *stream, uint64_t value);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to. 1-10 bytes will be written.
| value                | Value to encode, cast to `uint64_t`.
| returns              | True on success, false on IO error.

> **NOTE:** Value will be converted to `uint64_t` in the argument.
> To encode signed values, the argument should be cast to `int64_t` first for correct sign extension.

#### pb_encode_svarint

Encodes a signed integer in the [zig-zagged](https://developers.google.com/protocol-buffers/docs/encoding#signed_integers) format.
Works for fields of type `sint32` and `sint64`:

    bool pb_encode_svarint(pb_ostream_t *stream, int64_t value);

(parameters are the same as for [pb_encode_varint](#pb_encode_varint)

#### pb_encode_string

Writes the length of a string as varint and then contents of the string.
Works for fields of type `bytes` and `string`:

    bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to.
| buffer               | Pointer to string data.
| size                 | Number of bytes in the string. Pass `strlen(s)` for strings.
| returns              | True on success, false on IO error.

#### pb_encode_fixed32

Writes 4 bytes to stream and swaps bytes on big-endian architectures.
Works for fields of type `fixed32`, `sfixed32` and `float`:

    bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to. 4 bytes will be written.
| value                | Pointer to a 4-bytes large C variable, for example `uint32_t foo;`.
| returns              | True on success, false on IO error.

#### pb_encode_fixed64

Writes 8 bytes to stream and swaps bytes on big-endian architecture.
Works for fields of type `fixed64`, `sfixed64` and `double`:

    bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to. 8 bytes will be written.
| value                | Pointer to a 8-bytes large C variable, for example `uint64_t foo;`.
| returns              | True on success, false on IO error.

#### pb_encode_float_as_double

Encodes a 32-bit `float` value so that it appears like a 64-bit `double` in the encoded message.
This is sometimes needed when platforms like AVR that do not support 64-bit `double` need to communicate using a
message type that contains `double` fields.

    bool pb_encode_float_as_double(pb_ostream_t *stream, float value);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to. 8 bytes will be written.
| value                | Float value to encode.
| returns              | True on success, false on IO error.

#### pb_encode_submessage

Encodes a submessage field, including the size header for it. Works for
fields of any message type.

    bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Output stream to write to.
| fields               | Pointer to the autogenerated message descriptor for the submessage type, e.g. `MyMessage_fields`.
| src                  | Pointer to the structure where submessage data is.
| returns              | True on success, false on IO errors, pb_encode errors or if submessage size changes between calls.

In Protocol Buffers format, the submessage size must be written before
the submessage contents. Therefore, this function has to encode the
submessage twice in order to know the size beforehand.

If the submessage contains callback fields, the callback function might
misbehave and write out a different amount of data on the second call.
This situation is recognized and `false` is returned, but garbage will
be written to the output before the problem is detected.

## pb_decode.h

### pb_istream_from_buffer

Helper function for creating an input stream that reads data from a
memory buffer.

    pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| buf                  | Pointer to byte array to read from.
| bufsize              | Size of the byte array.
| returns              | An input stream ready to use.

### pb_read

Read data from input stream. Always use this function, don't try to
call the stream callback directly.

    bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from.
| buf                  | Buffer to store the data to, or `NULL` to just read data without storing it anywhere.
| count                | Number of bytes to read.
| returns              | True on success, false if `stream->bytes_left` is less than `count` or if an IO error occurs.

End of file is signalled by `stream->bytes_left` being zero after pb_read returns false.

### pb_decode

Read and decode all fields of a structure. Reads until EOF on input
stream.

    bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from.
| fields               | Message descriptor, usually autogenerated.
| dest_struct          | Pointer to message structure where data will be stored.
| returns              | True on success, false on any error condition. Error message will be in `stream->errmsg`.

In Protocol Buffers binary format, end-of-file is only allowed between fields.
If it happens anywhere else, pb_decode will return `false`. If
pb_decode returns `false`, you cannot trust any of the data in the
structure.

For optional fields, this function applies the default value and sets
`has_<field>` to false if the field is not present.

If `PB_ENABLE_MALLOC` is defined, this function may allocate storage
for any pointer type fields. In this case, you have to call
[pb_release](#pb_release) to release the memory after you are done with
the message. On error return `pb_decode` will release the memory itself.

### pb_decode_ex

Same as [pb_decode](#pb_decode), but allows extended options.

    bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from.
| fields               | Message descriptor, usually autogenerated.
| dest_struct          | Pointer to message structure where data will be stored.
| flags                | Extended options, see below
| returns              | True on success, false on any error condition. Error message will be in `stream->errmsg`.

The following options can be defined and combined with bitwise `|` operator:

* `PB_DECODE_NOINIT`: Do not initialize structure before decoding. This can be used to combine multiple messages, or if you have already initialized the message structure yourself.

* `PB_DECODE_DELIMITED`: Expect a length prefix in varint format before message. The counterpart of `PB_ENCODE_DELIMITED`.

* `PB_DECODE_NULLTERMINATED`: Expect the message to be terminated with zero tag. The counterpart of `PB_ENCODE_NULLTERMINATED`.

If `PB_ENABLE_MALLOC` is defined, this function may allocate storage
for any pointer type fields. In this case, you have to call
[pb_release](#pb_release) to release the memory after you are done with
the message. On error return `pb_decode_ex` will release the memory
itself.

### pb_release

Releases any dynamically allocated fields:

    void pb_release(const pb_msgdesc_t *fields, void *dest_struct);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| fields               | Message descriptor, usually autogenerated.
| dest_struct          | Pointer to structure where data is stored. If `NULL`, function does nothing.

This function is only available if `PB_ENABLE_MALLOC` is defined. It
will release any pointer type fields in the structure and set the
pointers to `NULL`.

This function is safe to call multiple times, calling it again does nothing.

### pb_decode_tag

Decode the tag that comes before field in the protobuf encoding:

    bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from.
| wire_type            | Pointer to variable where to store the wire type of the field.
| tag                  | Pointer to variable where to store the tag of the field.
| eof                  | Pointer to variable where to store end-of-file status.
| returns              | True on success, false on error or EOF.

When the message (stream) ends, this function will return `false` and set
`eof` to true. On other errors, `eof` will be set to false.

### pb_skip_field

Remove the data for a field from the stream, without actually decoding it:

    bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from.
| wire_type            | Type of field to skip.
| returns              | True on success, false on IO error.

This function determines the amount of bytes to read based on the wire type.
For `PB_WT_STRING`, it will read the length prefix of a string or submessage
to determine its length.

### Callback field decoders
The functions with names `pb_decode_<datatype>` are used when dealing with callback fields.
The typical reason for using callbacks is to have an array of unlimited size.
In that case, [pb_decode](#pb_decode) will call your callback function repeatedly,
which can then store the values into e.g. filesystem in the order received in.

For decoding numeric (including enumerated and boolean) values, use
[pb_decode_varint](#pb_decode_varint), [pb_decode_svarint](#pb_decode_svarint),
[pb_decode_fixed32](#pb_decode_fixed32) and [pb_decode_fixed64](#pb_decode_fixed64).
They take a pointer to a 32- or 64-bit C variable, which you may then cast to smaller datatype for storage.

For decoding strings and bytes fields, the length has already been decoded and the callback function is given a length-limited substream.
You can therefore check the total length in `stream->bytes_left` and read the data using [pb_read](#pb_read).

Finally, for decoding submessages in a callback, use [pb_decode](#pb_decode) and pass it the `SubMessage_fields` descriptor array.

#### pb_decode_varint

Read and decode a [varint](http://code.google.com/apis/protocolbuffers/docs/encoding.html#varints)
encoded integer.

    bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from. 1-10 bytes will be read.
| dest                 | Storage for the decoded integer. Value is undefined on error.
| returns              | True on success, false if value exceeds uint64_t range or an IO error happens.

#### pb_decode_varint32

Same as `pb_decode_varint`, but limits the value to 32 bits:

    bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest);

Parameters are the same as `pb_decode_varint`. This function can be used
for decoding lengths and other commonly occurring elements that you know
shouldn't be larger than 32 bit. It will return an error if the value
exceeds the `uint32_t` datatype.

#### pb_decode_svarint

Similar to [pb_decode_varint](#pb_decode_varint), except that it
performs zigzag-decoding on the value. This corresponds to the Protocol
Buffers `sint32` and `sint64` datatypes. :

    bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);

(parameters are the same as [pb_decode_varint](#pb_decode_varint))

#### pb_decode_fixed32

Decode a `fixed32`, `sfixed32` or `float` value.

    bool pb_decode_fixed32(pb_istream_t *stream, void *dest);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from. 4 bytes will be read.
| dest                 | Pointer to destination `int32_t`, `uint32_t` or `float`.
| returns              | True on success, false on IO errors.

This function reads 4 bytes from the input stream. On big endian
architectures, it then reverses the order of the bytes. Finally, it
writes the bytes to `dest`.

#### pb_decode_fixed64

Decode a `fixed64`, `sfixed64` or `double` value. :

    bool pb_decode_fixed64(pb_istream_t *stream, void *dest);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from. 8 bytes will be read.
| dest                 | Pointer to destination `int64_t`, `uint64_t` or `double`.
| returns              | True on success, false on IO errors.

Same as [pb_decode_fixed32](#pb_decode_fixed32), except this reads 8
bytes.

#### pb_decode_double_as_float

Decodes a 64-bit `double` value into a 32-bit `float`
variable. Counterpart of [pb_encode_float_as_double](#pb_encode_float_as_double). :

    bool pb_decode_double_as_float(pb_istream_t *stream, float *dest);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Input stream to read from. 8 bytes will be read.
| dest                 | Pointer to destination *float*.
| returns              | True on success, false on IO errors.

#### pb_make_string_substream

Decode the length for a field with wire type `PB_WT_STRING` and create
a substream for reading the data.

    bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Original input stream to read the length and data from.
| substream            | Storage for a new substream that has limited length. Filled in by the function.
| returns              | True on success, false if reading the length fails.

This function uses `pb_decode_varint` to read an integer from the stream.
This is interpreted as a number of bytes, and the substream is set up so that its `bytes_left` is initially the same as the
length, and its callback function and state the same as the parent stream.

#### pb_close_string_substream

Close the substream created with
[pb_make_string_substream](#pb_make_string_substream).

    void pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| stream               | Original input stream to read data from.
| substream            | Substream to close

This function copies back the state from the substream to the parent stream,
and throws away any unread data from the substream.
It must be called after done with the substream.

## pb_common.h

### pb_field_iter_begin

Begins iterating over the fields in a message type:

    bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| iter                 | Pointer to destination [pb_field_iter_t](#pb_field_iter_t) variable.
| desc                 | Autogenerated message descriptor.
| message              | Pointer to message structure.
| returns              | True on success, false if the message type has no fields.

### pb_field_iter_next

Advance to the next field in the message:

    bool pb_field_iter_next(pb_field_iter_t *iter);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| iter                 | Pointer to `pb_field_iter_t` previously initialized by [pb_field_iter_begin](#pb_field_iter_begin).
| returns              | True on success, false after last field in the message.

When the last field in the message has been processed, this function
will return false and initialize `iter` back to the first field in the
message.

### pb_field_iter_find

Find a field specified by tag number in the message:

    bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| iter                 | Pointer to `pb_field_iter_t` previously initialized by [pb_field_iter_begin](#pb_field_iter_begin).
| tag                  | Tag number to search for.
| returns              | True if field was found, false otherwise.

This function is functionally identical to calling `pb_field_iter_next()` until `iter.tag` equals the searched value.
Internally this function avoids fully processing the descriptor for intermediate fields.

### pb_validate_utf8

Validates an UTF8 encoded string:

    bool pb_validate_utf8(const char *s);

|                      |                                                        |
|----------------------|--------------------------------------------------------|
| s                    | Pointer to beginning of a string.
| returns              | True, if string is valid UTF-8, false otherwise.

The protobuf standard requires that `string` fields only contain valid
UTF-8 encoded text, while `bytes` fields can contain arbitrary data.
When the compilation option `PB_VALIDATE_UTF8` is defined, nanopb will
automatically validate strings on both encoding and decoding.

User code can call this function to validate strings in e.g. custom
callbacks.


# Nanopb: Security model

Importance of security in a Protocol Buffers library
----------------------------------------------------

In the context of protocol buffers, security comes into play when
decoding untrusted data. Naturally, if the attacker can modify the
contents of a protocol buffers message, he can feed the application any
values possible. Therefore the application itself must be prepared to
receive untrusted values.

Where nanopb plays a part is preventing the attacker from running
arbitrary code on the target system. Mostly this means that there must
not be any possibility to cause buffer overruns, memory corruption or
invalid pointers by the means of crafting a malicious message.

Division of trusted and untrusted data
--------------------------------------

The following data is regarded as **trusted**. It must be under the
control of the application writer. Malicious data in these structures
could cause security issues, such as execution of arbitrary code:

1.  Callback, pointer and extension fields in message structures given
    to pb_encode() and pb_decode(). These fields are memory pointers,
    and are generated depending on the message definition in the .proto
    file.
2.  The automatically generated field definitions, i.e.
    `pb_msgdesc_t`.
3.  Contents of the `pb_istream_t` and `pb_ostream_t` structures
    (this does not mean the contents of the stream itself, just the
    stream definition).

The following data is regarded as **untrusted**. Invalid/malicious data
in these will cause "garbage in, garbage out" behaviour. It will not
cause buffer overflows, information disclosure or other security
problems:

1.  All data read from `pb_istream_t`.
2.  All fields in message structures, except:
    -   callbacks (`pb_callback_t` structures)
    -   pointer fields and `_count` fields for pointers
    -   extensions (`pb_extension_t` structures)

Invariants
----------

The following invariants are maintained during operation, even if the
untrusted data has been maliciously crafted:

1.  Nanopb will never read more than `bytes_left` bytes from
    `pb_istream_t`.
2.  Nanopb will never write more than `max_size` bytes to
    `pb_ostream_t`.
3.  Nanopb will never access memory out of bounds of the message
    structure.
4.  After `pb_decode()` returns successfully, the message structure will
    be internally consistent:
    -   The `count` fields of arrays will not exceed the array size.
    -   The `size` field of bytes will not exceed the allocated size.
    -   All string fields will have null terminator.
    -   bool fields will have valid true/false values (since
        nanopb-0.3.9.4)
    -   pointer fields will be either `NULL` or point to valid data
5.  After `pb_encode()` returns successfully, the resulting message is a
    valid protocol buffers message. (Except if user-defined callbacks
    write incorrect data.)
6.  All memory allocated by `pb_decode()` will be released by a subsequent
    call to `pb_release()` on the same message.

Further considerations
----------------------

Even if the nanopb library is free of any security issues, there are
still several possible attack vectors that the application author must
consider. The following list is not comprehensive:

1.  Stack usage may depend on the contents of the message. The message
    definition places an upper bound on how much stack will be used.
    Tests should be run with all fields present, to record the maximum
    possible stack usage.
2.  Callbacks can do anything. The code for the callbacks must be
    carefully checked if they are used with untrusted data.
3.  If using stream input, a maximum size should be set in
    `pb_istream_t` to stop a denial of service attack from using an
    infinite message.
4.  If using network sockets as streams, a timeout should be set to stop
    denial of service attacks.
5.  If using `malloc()` support, some method of limiting memory use
    should be employed. This can be done by defining custom
    `pb_realloc()` function. Nanopb will properly detect and handle
    failed memory allocations.

This is the latest version of the internal repository from Pebble Technology providing the software to run on Pebble watches. Proprietary source code has been removed from this repository and it will not compile as-is. This is for information only.


# Nanopb: New features in nanopb 0.4

## What's new in nanopb 0.4

Long in the making, nanopb 0.4 has seen some wide reaching improvements
in reaction to the development of the rest of the protobuf ecosystem.
This document showcases features that are not immediately visible, but
that you may want to take advantage of.

A lot of effort has been spent in retaining backwards and forwards
compatibility with previous nanopb versions. For a list of breaking
changes, see [migration document](migration.html)

### New field descriptor format

The basic design of nanopb has always been that the information about
messages is stored in a compact descriptor format, which is iterated in
runtime. Initially it was very tightly tied with encoder and decoder
logic.

In nanopb-0.3.0 the field iteration logic was separated to
`pb_common.c`. Already at that point it was clear that the old format
was getting too limited, but it wasn't extended at that time.

Now in 0.4, the descriptor format was completely decoupled from the
encoder and decoder logic, and redesigned to meet new demands.
Previously each field was stored as `pb_field_t` struct, which was
between 8 and 32 bytes in size, depending on compilation options and
platform. Now information about fields is stored as a variable length
sequence of `uint32_t` data words. There are 1, 2, 4 and 8 word formats,
with the 8 word format containing plenty of space for future
extensibility.

One benefit of the variable length format is that most messages now take
less storage space. Most fields use 2 words, while simple fields in
small messages require only 1 word. Benefit is larger if code previously
required `PB_FIELD_16BIT` or `PB_FIELD_32BIT` options. In
the `AllTypes` test case, 0.3 had data size of 1008 bytes in
8-bit configuration and 1408 bytes in 16-bit configuration. New format
in 0.4 takes 896 bytes for either of these.

In addition, the new decoupling has allowed moving most of the field
descriptor data into FLASH on Harvard architectures, such as AVR.
Previously nanopb was quite RAM-heavy on AVR, which cannot put normal
constants in flash like most other platforms do.

### Python packaging for generator

Nanopb generator is now available as a Python package, installable using
`pip` package manager. This will reduce the need for binary
packages, as if you have Python already installed you can just
`pip install nanopb` and have the generator available on path as
`nanopb_generator`.

The generator can also take advantage of the Python-based `protoc`
available in `grpcio-tools` Python package. If you also install that,
there is no longer a need to have binary `protoc` available.

### Generator now automatically calls protoc

Initially, nanopb generator was used in two steps: first calling
`protoc` to parse the `.proto` file into `.pb` binary
format, and then calling `nanopb_generator.py` to output the
`.pb.h` and `.pb.c` files.

Nanopb 0.2.3 added support for running as a `protoc` plugin, which
allowed single-step generation using `--nanopb_out` parameter. However,
the plugin mode has two complications: passing options to nanopb
generator itself becomes more difficult, and the generator does not know
the actual path of input files. The second limitation has been
particularly problematic for locating `.options` files.

Both of these older methods still work and will remain supported.
However, now `nanopb_generator` can also take `.proto` files
directly and it will transparently call `protoc` in the background.

### Callbacks bound by function name

Since its very beginnings, nanopb has supported field callbacks to allow
processing structures that are larger than what could fit in memory at
once. So far the callback functions have been stored in the message
structure in a `pb_callback_t` struct.

Storing pointers along with user data is somewhat risky from a security
point of view. In addition it has caused problems with `oneof` fields,
which reuse the same storage space for multiple submessages. Because
there is no separate area for each submessage, there is no space to
store the callback pointers either.

Nanopb-0.4.0 introduces callbacks that are referenced by the function
name instead of setting the pointers separately. This should work well
for most applications that have a single callback function for each
message type. For more complex needs, `pb_callback_t` will also remain
supported.

Function name callbacks also allow specifying custom data types for
inclusion in the message structure. For example, you could have
`MyObject*` pointer along with other message fields, and then process
that object in custom way in your callback.

This feature is demonstrated in
[tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback) test case and
[examples/network_server](https://github.com/nanopb/nanopb/tree/master/examples/network_server) example.

### Message level callback for oneofs

As mentioned above, callbacks inside submessages inside oneofs have been
problematic to use. To make using `pb_callback_t`-style callbacks there
possible, a new generator option `submsg_callback` was added.

Setting this option to true will cause a new message level callback to
be added before the `which_field` of the oneof. This callback will be
called when the submessage tag number is known, but before the actual
message is decoded. The callback can either choose to set callback
pointers inside the submessage, or just completely decode the submessage
there and then. If any unread data remains after the callback returns,
normal submessage decoding will continue.

There is an example of this in [tests/oneof_callback](https://github.com/nanopb/nanopb/tree/master/tests/oneof_callback) test case.

### Binding message types to custom structures

It is often said that good C code is chock full of macros. Or maybe I
got it wrong. But since nanopb 0.2, the field descriptor generation has
heavily relied on macros. This allows it to automatically adapt to
differences in type alignment on different platforms, and to decouple
the Python generation logic from how the message descriptors are
implemented on the C side.

Now in 0.4.0, I've made the macros even more abstract. Time will tell
whether this was such a great idea that I think it is, but now the
complete list of fields in each message is available in `.pb.h` file.
This allows a kind of metaprogramming using [X-macros]()

One feature that this can be used for is binding the message descriptor
to a custom structure or C++ class type. You could have a bunch of other
fields in the structure and even the datatypes can be different to an
extent, and nanopb will automatically detect the size and position of
each field. The generated `.pb.c` files now just have calls of
`PB_BIND(msgname, structname, width)`. Adding a similar
call to your own code will bind the message to your own structure.

### UTF-8 validation

Protobuf format defines that strings should consist of valid UTF-8
codepoints. Previously nanopb has not enforced this, requiring extra
care in the user code. Now optional UTF-8 validation is available with
compilation option `PB_VALIDATE_UTF8`.

### Double to float conversion

Some platforms such as `AVR` do not support the `double`
datatype, instead making it an alias for `float`. This has resulted in
problems when trying to process message types containing `double` fields
generated on other machines. There has been an example on how to
manually perform the conversion between `double` and
`float`.

Now that example is integrated as an optional feature in nanopb core. By
defining `PB_CONVERT_DOUBLE_FLOAT`, the required conversion between 32-
and 64-bit floating point formats happens automatically on decoding and
encoding.

### Improved testing

Testing on embedded platforms has been integrated in the continuous
testing environment. Now all of the 80+ test cases are automatically run
on STM32 and AVR targets. Previously only a few specialized test cases
were manually tested on embedded systems.

Nanopb fuzzer has also been integrated in Google's [OSSFuzz](https://google.github.io/oss-fuzz/)
platform, giving a huge boost in the CPU power available for randomized
testing.


# pbl
Like pebble-tool, but for internal things.

Not to be confused with pebble-tool-dev. This repository is for internal tools
that don't make sense to ever be public; pebble-tool-dev is for public tools
that can't be public yet.

Not sure where to put something? Ask Katharine!

## Installation

    pip install git+ssh://git@github.com/pebble/pbl.git

## Adding commands

Create a new file in pbl/commands. Add a class inheriting from `BaseCommand`
(or `PebbleCommand` if it connects to a pebble). The docstring will be used as
help. Include a `command` field that gives the name of the command. The class's
`__call__` method will be called when you run the command.

Many examples can be found [in pebble-tool](https://github.com/pebble/pebble-tool/tree/master/pebble_tool/commands).


pblconvert
==========

pblconvert is a tool to convert pebble resources.
Today, it can be used to convert SVGs to PDCs.

Installing
-----------

```
$ pip install .
```

Running tests
-------------

```
$ nosetests tests
```

Usage
------

```
pblconvert --infile <input> [--informat --outfile --outformat]
```

One of [outformat|outfile] is required


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Animated Images
description: |
  How to add animated image resources to a project in the APNG format, and
  display them in your app.
guide_group: app-resources
order: 0
platform_choice: true
---

The Pebble SDK allows animated images to be played inside an app using the
``GBitmapSequence`` API, which takes [APNG](https://en.wikipedia.org/wiki/APNG)
images as input files. APNG files are similar to well-known `.gif` files, which
are not supported directly but can be converted to APNG.

A similar effect can be achieved with multiple image resources, a
``BitmapLayer`` and an ``AppTimer``, but would require a lot more code. The
``GBitmapSequence`` API handles the reading, decompression, and frame
duration/count automatically.

## Converting GIF to APNG

A `.gif` file can be converted to the APNG `.png` format with
[gif2apng](http://gif2apng.sourceforge.net/) and the `-z0` flag:

```text
./gif2apng -z0 animation.gif
```

> Note: The file extension must be `.png`, **not** `.apng`.

## Adding an APNG

{% platform local %}
Include the APNG file in the `resources` array in `package.json` as a `raw`
resource:

```js
"resources": {
  "media": [
    {
      "type":"raw",
      "name":"ANIMATION",
      "file":"images/animation.png"
    }
  ]
}
```
{% endplatform %}

{% platform cloudpebble %}
To add the APNG file as a raw resource, click 'Add New' in the Resources section
of the sidebar, and set the 'Resource Type' as 'raw binary blob'.
{% endplatform %}

## Displaying APNG Frames

The ``GBitmapSequence`` will use a ``GBitmap`` as a container and update its
contents each time a new frame is read from the APNG file. This means that the
first step is to create a blank ``GBitmap`` to be this container.

Declare file-scope variables to hold the data:

```c
static GBitmapSequence *s_sequence;
static GBitmap *s_bitmap;
```

Load the APNG from resources into the ``GBitmapSequence`` variable, and use the
frame size to create the blank ``GBitmap`` frame container:

```c
// Create sequence
s_sequence = gbitmap_sequence_create_with_resource(RESOURCE_ID_ANIMATION);

// Create blank GBitmap using APNG frame size
GSize frame_size = gbitmap_sequence_get_bitmap_size(s_sequence);
s_bitmap = gbitmap_create_blank(frame_size, GBitmapFormat8Bit);
```

Once the app is ready to begin playing the animated image, advance each frame
using an ``AppTimer`` until the end of the sequence is reached. Loading the next
APNG frame is handled for you and written to the container ``GBitmap``.

Declare a ``BitmapLayer`` variable to display the current frame, and set it up
as described under
{% guide_link app-resources/images#displaying-an-image "Displaying An Image" %}.

```c
static BitmapLayer *s_bitmap_layer;
```

Create the callback to be used when the ``AppTimer`` has elapsed, and the next
frame should be displayed. This will occur in a loop until there are no more
frames, and ``gbitmap_sequence_update_bitmap_next_frame()`` returns `false`:

```c
static void timer_handler(void *context) {
  uint32_t next_delay;

  // Advance to the next APNG frame, and get the delay for this frame
  if(gbitmap_sequence_update_bitmap_next_frame(s_sequence, s_bitmap, &next_delay)) {
    // Set the new frame into the BitmapLayer
    bitmap_layer_set_bitmap(s_bitmap_layer, s_bitmap);
    layer_mark_dirty(bitmap_layer_get_layer(s_bitmap_layer));

    // Timer for that frame's delay
    app_timer_register(next_delay, timer_handler, NULL);
  }
}
```

When appropriate, schedule the first frame advance with an ``AppTimer``:

```c
uint32_t first_delay_ms = 10;

// Schedule a timer to advance the first frame
app_timer_register(first_delay_ms, timer_handler, NULL);
```

When the app exits or the resource is no longer required, destroy the
``GBitmapSequence`` and the container ``GBitmap``:

```c
gbitmap_sequence_destroy(s_sequence);
gbitmap_destroy(s_bitmap);
```


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: App Assets
description: |
  A collection of assets for use as resources in Pebble apps.
guide_group: app-resources
order: 1
---

This guide contains some resources available for developers to use in their apps
to improve consistency, as well as for convenience. For example, most
``ActionBarLayer`` implementations will require at least one of the common icons
given below.

## Pebble Timeline Pin Icons

Many timeline pin icons
[are available]({{ site.links.s3_assets }}/assets/other/pebble-timeline-icons-pdc.zip)
in Pebble Draw Command or PDC format (as described in
{% guide_link graphics-and-animations/vector-graphics %}) for use in watchfaces
and watchapps. These are useful in many kinds of generic apps.

## Example PDC icon SVG Files

Many of the system PDC animations are available for use in watchfaces and
watchapps as part of the
[`pdc-sequence`](https://github.com/pebble-examples/pdc-sequence/tree/master/resources)
example project.

## Example Action Bar Icons

There is a
[set of example icons](https://s3.amazonaws.com/developer.getpebble.com/assets/other/actionbar-icons.zip)
for developers to use for common actions. Each icon is shown below as a preview,
along with a short description about its suggested usage.

| Preview | Description |
|---------|-------------|
| ![](/images/guides/design-and-interaction/icons/action_bar_icon_check.png) | Check mark for confirmation actions. |
| ![](/images/guides/design-and-interaction/icons/action_bar_icon_dismiss.png) | Cross mark for dismiss, cancel, or decline actions. |
| ![](/images/guides/design-and-interaction/icons/action_bar_icon_up.png) | Up arrow for navigating or scrolling upwards. |
| ![](/images/guides/design-and-interaction/icons/action_bar_icon_down.png) | Down arrow for navigating or scrolling downwards. |
| ![](/images/guides/design-and-interaction/icons/action_bar_icon_edit.png) | Pencil icon for edit actions. |
| ![](/images/guides/design-and-interaction/icons/action_bar_icon_delete.png) | Trash can icon for delete actions. |
| ![](/images/guides/design-and-interaction/icons/action_bar_icon_snooze.png) | Stylized 'zzz' for snooze actions. |
| ![](/images/guides/design-and-interaction/icons/music_icon_ellipsis.png) | Ellipsis to suggest further information or actions are available. |
| ![](/images/guides/design-and-interaction/icons/music_icon_play.png) | Common icon for play actions. |
| ![](/images/guides/design-and-interaction/icons/music_icon_pause.png) | Common icon for pause actions. |
| ![](/images/guides/design-and-interaction/icons/music_icon_skip_forward.png) | Common icon for skip forward actions. |
| ![](/images/guides/design-and-interaction/icons/music_icon_skip_backward.png) | Common icon for skip backward actions. |
| ![](/images/guides/design-and-interaction/icons/music_icon_volume_up.png) | Common icon for raising volume. |
| ![](/images/guides/design-and-interaction/icons/music_icon_volume_down.png) | Common icon for lowering volume. |


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Converting SVG to PDC
description: |
  How to create compatible SVG files using Inkscape and Illustrator.
guide_group: app-resources
order: 2
related_docs:
  - Draw Commands
---

[Pebble Draw Commands](``Draw Commands``) (PDC) are a powerful method of
creating vector images and icons that can be transformed and manipulated at
runtime. These can be used as a low-cost alternative to APNGs or bitmap
sequences. Currently the only simple way to create PDC files is to use the
[`svg2pdc.py`](https://github.com/pebble-examples/cards-example/blob/master/tools/svg2pdc.py)
tool. However, as noted in
[*Vector Animations*](/tutorials/advanced/vector-animations/#creating-compatible-files)
there are a some limitations to the nature of the input SVG file:

> The `svg2pdc` tool currently supports SVG files that use **only** the
> following elements: `g`, `layer`, `path`, `rect`, `polyline`, `polygon`,
> `line`, `circle`.

Fortunately, steps can be taken when creating SVG files in popular graphics
packages to avoid these limitations and ensure the output file is compatible
with `svg2pdc.py`. In this guide, we will be creating compatible PDC files using
an example SVG - this
[pencil icon](https://upload.wikimedia.org/wikipedia/commons/a/ac/Black_pencil.svg).

![pencil icon](/images/guides/pebble-apps/resources/pencil.svg =100x)

## Using Inkscape

* First, open the SVG in [Inkscape](https://inkscape.org/en/):

![inkscape-open](/images/guides/pebble-apps/resources/inkscape-open.png)

* Resize the viewport with *File*, *Document Properties*,
  *Page*, *Resize Page to Drawing*:

![inkscape-resize-page](/images/guides/pebble-apps/resources/inkscape-resize-page.png =350x)

* Select the layer, then resize the image to fit Pebble (50 x 50 pixels in this
  example) with *Object*, *Transform*:

![inkscape-resize-pebble](/images/guides/pebble-apps/resources/inkscape-resize-pebble.png)

* Now that the image has been resized, shrink the viewport again with *File*,
  *Document Properties*, *Page*, *Resize Page to Drawing*:

* Remove groupings with *Edit*, *Select All*, then *Object*, *Ungroup* until no
  groups remain:

![inkscape-ungroup](/images/guides/pebble-apps/resources/inkscape-ungroup.png)

* Disable relative move in *Object*, *Transform*. Hit *Apply*:

![inkscape-relative](/images/guides/pebble-apps/resources/inkscape-relative.png)

* Finally, save the image as a 'Plain SVG':

![inkscape-plain](/images/guides/pebble-apps/resources/inkscape-plain.png)

## Using Illustrator

* First, open the SVG in Illustrator:

![illustrator-open](/images/guides/pebble-apps/resources/illustrator-open.png)

* Resize the image to fit Pebble (50 x 50 pixels in this example) by entering in
  the desired values in the 'W' and 'H' fields of the *Transform* panel:

![illustrator-resize](/images/guides/pebble-apps/resources/illustrator-resize.png)

* Ungroup all items with *Select*, *All*, followed by *Object*, *Ungroup* until
  no groups remain:

![illustrator-ungroup](/images/guides/pebble-apps/resources/illustrator-ungroup.png)

* Shrink the image bounds with *Object*, *Artboards*, *Fit to Selected Art*:

![illustrator-fit](/images/guides/pebble-apps/resources/illustrator-fit.png)

* Save the SVG using *File*, *Save As* with the *SVG Tiny 1.1* profile and 1 decimal places:

![illustrator-settings](/images/guides/pebble-apps/resources/illustrator-settings.png =350x)

## Using the PDC Files

Once the compatible SVG files have been created, it's time to use `svg2pdc.py`
to convert into PDC resources, which will contain all the vector information
needed to draw the image in the correct Pebble binary format. The command is
shown below, with the Inkscape output SVG used as an example:

```nc|bash
$ python svg2pdc.py pencil-inkscape.svg  # Use python 2.x!
```

> If a coordinate value's precision value isn't supported, a warning will be
> printed and the nearest compatible value will be used instead:
>
> ```text
> Invalid point: (9.4, 44.5). Closest supported coordinate: (9.5, 44.5)
> ```

To use the PDC file in a Pebble project, read
[*Drawing a PDC Image*](/tutorials/advanced/vector-animations/#drawing-a-pdc-image).
The result should look near-identical on Pebble:

![svg-output >{pebble-screenshot,pebble-screenshot--time-red}](/images/guides/pebble-apps/resources/svg-output.png)

## Example Output

For reference, compatible output files are listed below:

* Inkscape: [SVG](/assets/other/pdc/pencil-inkscape.svg) | [PDC](/assets/other/pdc/pencil-inkscape.pdc)

* Illustrator: [SVG](/assets/other/pdc/pencil-illustrator.svg) | [PDC](/assets/other/pdc/pencil-illustrator.pdc)


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Fonts
description: |
  How to use built-in system fonts, or add your own font resources to a project.
guide_group: app-resources
order: 3
platform_choice: true
---

## Using Fonts

Text drawn in a Pebble app can be drawn using a variety of built-in fonts or a
custom font specified as a project resource.

Custom font resources must be in the `.ttf` (TrueType font) format. When the app
is built, the font file is processed by the SDK according to the `compatibility`
(See [*Font Compatibility*](#font-compatibility)) and `characterRegex`
fields (see [*Choosing Font Characters*](#choosing-font-characters)), the latter
of which is a standard Python regex describing the character set of the
resulting font.

## System Fonts

All of the built-in system fonts are available to use with
``fonts_get_system_font()``. See {% guide_link app-resources/system-fonts %} for
a complete list with sample images. Examples of using a built-in system font in
code are [shown below](#using-a-system-font).

### Limitations

There are limitations to the Bitham, Roboto, Droid and LECO fonts, owing to the
memory space available on Pebble, which only contain a subset of the default
character set.

* Roboto 49 Bold Subset - contains digits and a colon.
* Bitham 34/42 Medium Numbers - contain digits and a colon.
* Bitham 18/34 Light Subset - only contains a few characters and is not suitable
  for displaying general text.
* LECO Number sets - suitable for number-only usage.

## Using a System Font

Using a system font is the easiest choice when displaying simple text. For more
advanced cases, a custom font may be advantageous. A system font can be obtained
at any time, and the developer is not responsible for destroying it when they
are done with it. Fonts can be used in two modes:

```c
// Use a system font in a TextLayer
text_layer_set_font(s_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_24));
```

```c
// Use a system font when drawing text manually
graphics_draw_text(ctx, text, fonts_get_system_font(FONT_KEY_GOTHIC_24), bounds,
                     GTextOverflowModeWordWrap, GTextAlignmentCenter, NULL);
```

## Adding a Custom Font

{% platform local %}
After placing the font file in the project's `resources` directory, the custom
font can be added to a project as `font` `type` item in the `media` array in
`package.json`. The `name` field's contents will be made available at compile
time with `RESOURCE_ID_` at the front, and must end with the desired font size.
For example:

```js
"resources": {
  "media": [
    {
      "type": "font",
      "name": "EXAMPLE_FONT_20",
      "file": "example_font.ttf"
    }
  ]
}
```
{% endplatform %}

{% platform cloudpebble %}
To add a custom font file to your project, click 'Add New' in the Resources
section of the sidebar. Set the 'Resource Type' to 'TrueType font', and upload
the file using the 'Choose file' button. Choose an 'Identifier', which will be
made available at compile time with `RESOURCE_ID_` at the front. This must end
with the desired font size ("EXAMPLE_FONT_20", for example).

Configure the other options as appropriate, then hit 'Save' to save the
resource.
{% endplatform %}

{% alert important %}
The maximum recommended font size is 48.
{% endalert %}

## Using a Custom Font

Unlike a system font, a custom font must be loaded and unloaded by the
developer. Once this has been done, the font can easily be used in a similar
manner.

When the app initializes, load the font from resources using the generated
`RESOURCE_ID`:

```c
// Declare a file-scope variable
static GFont s_font;
```

```c
// Load the custom font
s_font = fonts_load_custom_font(
                          resource_get_handle(RESOURCE_ID_EXAMPLE_FONT_20));
```

The font can now be used in two modes - with a ``TextLayer``, or when drawing
text manually in a ``LayerUpdateProc``:

```c
// Use a custom font in a TextLayer
text_layer_set_font(s_text_layer, s_font);
```

```c
// Use a custom font when drawing text manually
graphics_draw_text(ctx, text, s_font, bounds, GTextOverflowModeWordWrap,
                                                  GTextAlignmentCenter, NULL);
```

## Font Compatibility

The font rendering process was improved in SDK 2.8. However, in some cases this
may cause the appearance of custom fonts to change slightly. To revert to the
old rendering process, add `"compatibility": "2.7"` to your font's object in the
`media` array (shown above) in `package.json` or set the 'Compatibility'
property in the font's resource view in CloudPebble to '2.7 and earlier'.

## Choosing Font Characters

By default, the maximum number of supported characters is generated for a font
resource. In most cases this will be far too many, and can bloat the size of the
app. To optimize the size of your font resources you can use a standard regular
expression (or 'regex') string to limit the number of characters to only those
you require.

The table below outlines some example regular expressions to use for limiting
font character sets in common watchapp scenarios:

| Expression | Result |
|------------|--------|
| `[ -~]` | ASCII characters only. |
| `[0-9]` | Numbers only. |
| `[0-9 ]` | Numbers and spaces only. |
| `[a-zA-Z]` | Letters only. |
| `[a-zA-Z ]` | Letters and spaces only. |
| `[0-9:APM ]` | Time strings only (e.g.: "12:45 AM"). |
| `[0-9:A-Za-z ]` | Time and date strings (e.g.: "12:43 AM Wednesday 3rd March 2015". |
| `[0-9:A-Za-z° ]` | Time, date, and degree symbol for temperature gauges. |
| `[0-9°CF ]` | Numbers and degree symbol with 'C' and 'F' for temperature gauges. |

{% platform cloudpebble %}
Open the font's configuration screen under 'Resources', then enter the desired
regex in the 'Characters' field. Check the preview of the new set of characters,
then choose 'Save'.
{% endplatform %}

{% platform local %}
Add the `characterRegex` key to any font objects in `package.json`'s
`media` array.

```js
"media": [
  {
    "characterRegex": "[:0-9]",
    "type": "font",
    "name": "EXAMPLE_FONT",
    "file": "example_font.ttf"
  }
]
```
{% endplatform %}

Check out
[regular-expressions.info](http://www.regular-expressions.info/tutorial.html)
to learn more about how to use regular expressions.


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Images
description: |
  How to add image resources to a project and display them in your app.
guide_group: app-resources
order: 4
platform_choice: true
---

Images can be displayed in a Pebble app by adding them as a project resource.
They are stored in memory as a ``GBitmap`` while the app is running, and can be
displayed either in a ``BitmapLayer`` or by using
``graphics_draw_bitmap_in_rect()``.

## Creating an Image

In order to be compatible with Pebble, the image should be saved as a PNG file,
ideally in a palettized format (see below for palette files) with the
appropriate number of colors. The number of colors available on each platform is
shown below:

| Platform | Number of Colors |
|----------|------------------|
| Aplite | 2 (black and white) |
| Basalt | 64 colors |
| Chalk | 64 colors |

## Color Palettes

Palette files for popular graphics packages that contain the 64 supported colors
are available below. Use these when creating color image resources:

* [Photoshop `.act`](/assets/other/pebble_colors_64.act)

* [Illustrator `.ai`](/assets/other/pebble_colors_64.ai)

* [GIMP `.pal`](/assets/other/pebble_colors_64.pal)

* [ImageMagick `.gif`](/assets/other/pebble_colors_64.gif)

## Import the Image

{% platform cloudpebble %}
Add the `.png` file as a resource using the 'Add New' button next to
'Resources'. Give the resource a suitable 'Identifier' such as 'EXAMPLE_IMAGE'
and click 'Save'.
{% endplatform %}

{% platform local %}
After placing the image in the project's `resources` directory, add an entry to
the `resources` item in `package.json`. Specify the `type` as `bitmap`, choose a
`name` (to be used in code) and supply the path relative to the project's
`resources` directory. Below is an example:

```js
"resources": {
  "media": [
    {
      "type": "bitmap",
      "name": "EXAMPLE_IMAGE",
      "file": "background.png"
    }
  ]
},
```
{% endplatform %}

## Specifying an Image Resource

Image resources are used in a Pebble project when they are listed using the
`bitmap` resource type.

Resources of this type can be optimized using additional attributes:

| Attribute | Description | Values |
|-----------|-------------|--------|
| `memoryFormat` | Optional. Determines the bitmap type. Reflects values in the `GBitmapFormat` `enum`. | `Smallest`, `SmallestPalette`, `1Bit`, `8Bit`, `1BitPalette`, `2BitPalette`, or `4BitPalette`. |
| `storageFormat` | Optional. Determines the file format used for storage. Using `spaceOptimization` instead is preferred. | `pbi` or `png`. |
| `spaceOptimization` | Optional. Determines whether the output resource is optimized for low runtime memory or low resource space usage. | `storage` or `memory`. |

{% platform cloudpebble %}
These attributes can be selected in CloudPebble from the resource's page:

![](/images/guides/app-resources/cp-bitmap-attributes.png)
{% endplatform %}

{% platform local %}
An example usage of these attributes in `package.json` is shown below:

```js
{
  "type": "bitmap",
  "name": "IMAGE_EXAMPLE",
  "file": "images/example_image.png"
  "memoryFormat": "Smallest",
  "spaceOptimization": "memory"
}
```
{% endplatform %}

On all platforms `memoryFormat` will default to `Smallest`. On Aplite
`spaceOptimization` will default to `memory`, and `storage` on all other
platforms.

> If you specify a combination of attributes that is not supported, such as a
> `1Bit` unpalettized PNG, the build will fail. Palettized 1-bit PNGs are
> supported.

When compared to using image resources in previous SDK versions:

* `png` is equivalent to `bitmap` with no additional specifiers.

* `pbi` is equivalent to `bitmap` with `"memoryFormat": "1Bit"`.

* `pbi8` is equivalent to `bitmap` with `"memoryFormat": "8Bit"` and
  `"storageFormat": "pbi"`.

Continuing to use the `png` resource type will result in a `bitmap` resource
with `"storageFormat": "png"`, which is not optimized for memory usage on the
Aplite platform due to less memory available in total, and is not encouraged.

## Specifying Resources Per Platform

To save resource space, it is possible to include only certain image resources
when building an app for specific platforms. For example, this is useful for the
Aplite platform, which requires only black and white versions of images, which
can be significantly smaller in size. Resources can also be selected according
to platform and display shape.

Read {% guide_link app-resources/platform-specific %} to learn more about how to
do this.

## Displaying an Image

Declare a ``GBitmap`` pointer. This will be the object type the image data is
stored in while the app is running:

```c
static GBitmap *s_bitmap;
```

{% platform cloudpebble %}
Create the ``GBitmap``, specifying the 'Identifier' chosen earlier, prefixed
with `RESOURCE_ID_`. This will manage the image data:
{% endplatform %}

{% platform local %}
Create the ``GBitmap``, specifying the `name` chosen earlier, prefixed with
`RESOURCE_ID_`. This will manage the image data:
{% endplatform %}

```c
s_bitmap = gbitmap_create_with_resource(RESOURCE_ID_EXAMPLE_IMAGE);
```

Declare a ``BitmapLayer`` pointer:

```c
static BitmapLayer *s_bitmap_layer;
```

Create the ``BitmapLayer`` and set it to show the ``GBitmap``. Make sure to
supply the correct width and height of your image in the ``GRect``, as well as
using ``GCompOpSet`` to ensure color transparency is correctly applied:

```c
s_bitmap_layer = bitmap_layer_create(GRect(5, 5, 48, 48));
bitmap_layer_set_compositing_mode(s_bitmap_layer, GCompOpSet);
bitmap_layer_set_bitmap(s_bitmap_layer, s_bitmap);
```

Add the ``BitmapLayer`` as a child layer to the ``Window``:

```c
layer_add_child(window_get_root_layer(window),
                                      bitmap_layer_get_layer(s_bitmap_layer));
```

Destroy both the ``GBitmap`` and ``BitmapLayer`` when the app exits:

```c
gbitmap_destroy(s_bitmap);
bitmap_layer_destroy(s_bitmap_layer);
```


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: App Resources
description: |
  Information on the many kinds of files that can be used inside Pebble apps.
guide_group: app-resources
menu: false
permalink: /guides/app-resources/
generate_toc: false
hide_comments: true
platform_choice: true
---

The Pebble SDK allows apps to include extra files as app resources. These files
can include images, animated images, vector images, custom fonts, and raw data
files. These resources are stored in flash memory and loaded when required by
the SDK. Apps that use a large number of resources should consider only keeping
in memory those that are immediately required.

{% alert notice %}
The maximum number of resources an app can include is **256**. In addition, the
maximum size of all resources bundled into a built app is **128 kB** on the
Aplite platform, and **256 kB** on the Basalt and Chalk platforms. These limits
include resources used by included Pebble Packages.
{% endalert %}

{% platform local %}
App resources are included in a project by being listed in the `media` property
of `package.json`, and are converted into suitable firmware-compatible formats
at build time. Examples of this are shown in each type of resource's respective
guide.
{% endplatform %}

{% platform cloudpebble %}
App resources are included in a project by clicking the 'Add New' button under
'Resources' and specifying the 'Resource Type' as appropriate. These are then
converted into suitable firmware-compatible formats at build time.
{% endplatform %}

## Contents

{% include guides/contents-group.md group=page.group_data %}


---
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

title: Pebble Draw Command File Format
description: |
  The binary file format description for Pebble Draw Command Frames, Images and
  Sequences.
guide_group: app-resources
order: 5
related_docs:
  - Draw Commands
  - LayerUpdateProc
  - Graphics
related_examples:
  - title: PDC Sequence
    url: https://github.com/pebble-examples/pdc-sequence
  - title: Weather Cards Example
    url: https://github.com/pebble-examples/cards-example
---

Pebble [`Draw Commands`](``Draw Commands``) (PDCs) are vector image files that
consist of a binary resource containing the instructions for each stroke, fill,
etc. that makes up the image. The byte format of all these components are
described in tabular form below.

> **Important**: All fields are in the little-endian format!

An example implementation with some
[usage limitations](/tutorials/advanced/vector-animations#creating-compatible-files)
can be seen in
[`svg2pdc.py`]({{site.links.examples_org}}/cards-example/blob/master/tools/svg2pdc.py).

## Component Types

A PDC binary file consists of the following key components, in ascending order
of abstraction:

* [Draw Command](#pebble-draw-command) - an instruction for a single line or
  path to be drawn.

* [Draw Command List](#pebble-draw-command-list) - a set of Draw Commands that
  make up a shape.

* [Draw Command Frame](#pebble-draw-command-frame) - a Draw Command List with
  configurable duration making up one animation frame. Many of these are used in
  a Draw Command Sequence.

* [Draw Command Image](#pebble-draw-command-image) - A single vector image.

* [Draw Command Sequence](#pebble-draw-command-sequence) - A set of Draw Command
  Frames that make up an animated sequence of vector images.

## Versions

| PDC Format Version | Implemented |
|--------------------|-------------|
| 1 | Firmware 3.0 |

## File Format Components

### Point

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| X | 0 | 2 | X axis coordinate. Has one of two formats depending on the Draw Command type (see below):

Path/Circle type: signed integer.
Precise path type: 13.3 fixed point. |
| Y | 2 | 2 | Y axis coordinate. Has one of two formats depending on the Draw Command type (see below):

Path/Circle type: signed integer.
Precise path type: 13.3 fixed point. |

### View Box

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Width | 0 | 2 | Width of the view box (signed integer). |
| Height | 2 | 2 | Height of the view box (signed integer). |

### Pebble Draw Command

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Type | 0 | 1 | Draw command type. Possible values are:

`0` - Invalid
`1` - Path
`2` - Circle
`3` - Precise path |
| Flags | 1 | 1 | Bit 0: Hidden (Draw Command should not be drawn).
 Bits 1-7: Reserved. |
| Stroke color | 2 | 1 | Pebble color (integer). |
| Stroke width | 3 | 1 | Stroke width (unsigned integer). |
| Fill color | 4 | 1 | Pebble color (integer). |
| Path open/radius | 5 | 2 | Path/Precise path type: Bit 0 indicates whether or not the path is drawn open (`1`) or closed (`0`).
Circle type: radius of the circle. |
| Number of points | 7 | 2 | Number of points (n) in the point array. See below. |
| Point array | 9 | n x 4 | The number of points (n) points. |

### Pebble Draw Command List

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Number of commands | 0 | 2 | Number of Draw Commands in this Draw Command List. (`0` is invalid). |
| Draw Command array | 2 | n x size of Draw Command  | List of Draw Commands in the format [specified above](#pebble-draw-command). |

### Pebble Draw Command Frame

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Duration | 0 | 2 | Duration of the frame in milliseconds. If `0`, the frame will not be shown at all (unless it is the last frame in a sequence). |
| Command list | 2 | Size of Draw Command List | Pebble Draw Command List in the format [specified above](#pebble-draw-command-list). |

### Pebble Draw Command Image

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Version | 8 | 1 | File version. |
| Reserved | 9 | 1 | Reserved field. Must be `0`. |
| [View box](#view-box) | 10 | 4 | Bounding box of the image. All Draw Commands are drawn relative to the top left corner of the view box. |
| Command list | 14 | Size of Draw Command List | Pebble Draw Command List in the format [specified above](#pebble-draw-command-list). |

### Pebble Draw Command Sequence

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Version | 8 | 1 | File version. |
| Reserved | 9 | 1 | Reserved field. Must be `0`. |
| [View box](#view-box) | 10 | 4 | Bounding box of the sequence. All Draw Commands are drawn relative to the top left corner of the view box. |
| Play count | 14 | 2 | Number of times to repeat the sequence. A value of `0` will result in no playback at all, whereas a value of `0xFFFF` will repeat indefinitely. |
| Frame count | 16 | 2 | Number of frames in the sequence. `0` is invalid. |
| Frame list | 18 | n x size of Draw Command Frame | Array of Draw Command Frames in the format [specified above](#pebble-draw-command-frame). |

## File Formats

### Pebble Draw Command Image File

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Magic word | 0 | 4 | ASCII characters spelling "PDCI". |
| Image size | 4 | 4 | Size of the Pebble Draw Command Image (in bytes). |
| Image | 8 | Size of Pebble Draw Command Image. | The Draw Command Image in the format [specified above](#pebble-draw-command-image). |

### Pebble Draw Command Sequence File

| Field | Offset (bytes) | Size (bytes) | Description |
|-------|----------------|--------------|-------------|
| Magic word | 0 | 4 | ASCII characters spelling "PDCS". |
| Sequence size | 4 | 4 | Size of the Pebble Draw Command Sequence (in bytes). |
| Sequence | 8 | Size of Draw Command Sequence | The Draw Command Sequence in the format [specified above](#pebble-draw-command-sequence). |