protobuf-c/protobuf-c/protobuf-c.h
2022-07-10 21:33:59 -04:00

1111 lines
33 KiB
C
Executable File

/*
* Copyright (c) 2008-2022, Dave Benson and the protobuf-c authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*! \file
* \mainpage Introduction
*
* This is [protobuf-c], a C implementation of [Protocol Buffers].
*
* This file defines the public API for the `libprotobuf-c` support library.
* This API includes interfaces that can be used directly by client code as well
* as the interfaces used by the code generated by the `protoc-c` compiler.
*
* The `libprotobuf-c` support library performs the actual serialization and
* deserialization of Protocol Buffers messages. It interacts with structures,
* definitions, and metadata generated by the `protoc-c` compiler from .proto
* files.
*
* \authors Dave Benson and the `protobuf-c` authors.
*
* \copyright 2008-2014. Licensed under the terms of the [BSD-2-Clause] license.
*
* [protobuf-c]: https://github.com/protobuf-c/protobuf-c
* [Protocol Buffers]: https://developers.google.com/protocol-buffers/
* [BSD-2-Clause]: http://opensource.org/licenses/BSD-2-Clause
*
* \page gencode Generated Code
*
* For each enum, we generate a C enum. For each message, we generate a C
* structure which can be cast to a `ProtobufCMessage`.
*
* For each enum and message, we generate a descriptor object that allows us to
* implement a kind of reflection on the structures.
*
* First, some naming conventions:
*
* - The name of the type for enums and messages and services is camel case
* (meaning WordsAreCrammedTogether) except that double underscores are used
* to delimit scopes. For example, the following `.proto` file:
*
~~~{.proto}
package foo.bar;
message BazBah {
optional int32 val = 1;
}
~~~
*
* would generate a C type `Foo__Bar__BazBah`.
*
* - Identifiers for functions and globals are all lowercase, with camel case
* words separated by single underscores. For example, one of the function
* prototypes generated by `protoc-c` for the above example:
*
~~~{.c}
Foo__Bar__BazBah *
foo__bar__baz_bah__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
~~~
*
* - Identifiers for enum values contain an uppercase prefix which embeds the
* package name and the enum type name.
*
* - A double underscore is used to separate further components of identifier
* names.
*
* For example, in the name of the unpack function above, the package name
* `foo.bar` has become `foo__bar`, the message name BazBah has become
* `baz_bah`, and the method name is `unpack`. These are all joined with double
* underscores to form the C identifier `foo__bar__baz_bah__unpack`.
*
* We also generate descriptor objects for messages and enums. These are
* declared in the `.pb-c.h` files:
*
~~~{.c}
extern const ProtobufCMessageDescriptor foo__bar__baz_bah__descriptor;
~~~
*
* The message structures all begin with `ProtobufCMessageDescriptor *` which is
* sufficient to allow them to be cast to `ProtobufCMessage`.
*
* For each message defined in a `.proto` file, we generate a number of
* functions and macros. Each function name contains a prefix based on the
* package name and message name in order to make it a unique C identifier.
*
* - `INIT`. Statically initializes a message object, initializing its
* descriptor and setting its fields to default values. Uninitialized
* messages cannot be processed by the protobuf-c library.
*
~~~{.c}
#define FOO__BAR__BAZ_BAH__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&foo__bar__baz_bah__descriptor), 0 }
~~~
* - `init()`. Initializes a message object, initializing its descriptor and
* setting its fields to default values. Uninitialized messages cannot be
* processed by the protobuf-c library.
*
~~~{.c}
void foo__bar__baz_bah__init
(Foo__Bar__BazBah *message);
~~~
* - `unpack()`. Unpacks data for a particular message format. Note that the
* `allocator` parameter is usually `NULL` to indicate that the system's
* `malloc()` and `free()` functions should be used for dynamically allocating
* memory.
*
~~~{.c}
Foo__Bar__BazBah *
foo__bar__baz_bah__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
~~~
*
* - `free_unpacked()`. Frees a message object obtained with the `unpack()`
* method. Freeing `NULL` is allowed (the same as with `free()`).
*
~~~{.c}
void foo__bar__baz_bah__free_unpacked
(Foo__Bar__BazBah *message,
ProtobufCAllocator *allocator);
~~~
*
* - `get_packed_size()`. Calculates the length in bytes of the serialized
* representation of the message object.
*
~~~{.c}
size_t foo__bar__baz_bah__get_packed_size
(const Foo__Bar__BazBah *message);
~~~
*
* - `pack()`. Pack a message object into a preallocated buffer. Assumes that
* the buffer is large enough. (Use `get_packed_size()` first.)
*
~~~{.c}
size_t foo__bar__baz_bah__pack
(const Foo__Bar__BazBah *message,
uint8_t *out);
~~~
*
* - `pack_to_buffer()`. Packs a message into a "virtual buffer". This is an
* object which defines an "append bytes" callback to consume data as it is
* serialized.
*
~~~{.c}
size_t foo__bar__baz_bah__pack_to_buffer
(const Foo__Bar__BazBah *message,
ProtobufCBuffer *buffer);
~~~
*
* \page pack Packing and unpacking messages
*
* To pack a message, first compute the packed size of the message with
* protobuf_c_message_get_packed_size(), then allocate a buffer of at least
* that size, then call protobuf_c_message_pack().
*
* Alternatively, a message can be serialized without calculating the final size
* first. Use the protobuf_c_message_pack_to_buffer() function and provide a
* ProtobufCBuffer object which implements an "append" method that consumes
* data.
*
* To unpack a message, call the protobuf_c_message_unpack() function. The
* result can be cast to an object of the type that matches the descriptor for
* the message.
*
* The result of unpacking a message should be freed with
* protobuf_c_message_free_unpacked().
*/
#ifndef PROTOBUF_C_H
#define PROTOBUF_C_H
#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
# define PROTOBUF_C__BEGIN_DECLS extern "C" {
# define PROTOBUF_C__END_DECLS }
#else
# define PROTOBUF_C__BEGIN_DECLS
# define PROTOBUF_C__END_DECLS
#endif
PROTOBUF_C__BEGIN_DECLS
#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB)
# ifdef PROTOBUF_C_EXPORT
# define PROTOBUF_C__API __declspec(dllexport)
# else
# define PROTOBUF_C__API __declspec(dllimport)
# endif
#else
# define PROTOBUF_C__API
#endif
#if !defined(PROTOBUF_C__NO_DEPRECATED) && \
((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
# define PROTOBUF_C__DEPRECATED __attribute__((__deprecated__))
#else
# define PROTOBUF_C__DEPRECATED
#endif
#ifndef PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE
#define PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(enum_name) \
, _##enum_name##_IS_INT_SIZE = INT_MAX
#endif
#define PROTOBUF_C__SERVICE_DESCRIPTOR_MAGIC 0x14159bc3
#define PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC 0x28aaeef9
#define PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC 0x114315af
/* Empty string used for initializers */
#if defined(_WIN32) && defined(PROTOBUF_C_USE_SHARED_LIB)
static const char protobuf_c_empty_string[] = "";
#else
extern const char protobuf_c_empty_string[];
#endif
/**
* \defgroup api Public API
*
* This is the public API for `libprotobuf-c`. These interfaces are stable and
* subject to Semantic Versioning guarantees.
*
* @{
*/
/**
* Values for the `flags` word in `ProtobufCFieldDescriptor`.
*/
typedef enum {
/** Set if the field is repeated and marked with the `packed` option. */
PROTOBUF_C_FIELD_FLAG_PACKED = (1 << 0),
/** Set if the field is marked with the `deprecated` option. */
PROTOBUF_C_FIELD_FLAG_DEPRECATED = (1 << 1),
/** Set if the field is a member of a oneof (union). */
PROTOBUF_C_FIELD_FLAG_ONEOF = (1 << 2),
} ProtobufCFieldFlag;
/**
* Message field rules.
*
* \see [Defining A Message Type] in the Protocol Buffers documentation.
*
* [Defining A Message Type]:
* https://developers.google.com/protocol-buffers/docs/proto#simple
*/
typedef enum {
/** A well-formed message must have exactly one of this field. */
PROTOBUF_C_LABEL_REQUIRED,
/**
* A well-formed message can have zero or one of this field (but not
* more than one).
*/
PROTOBUF_C_LABEL_OPTIONAL,
/**
* This field can be repeated any number of times (including zero) in a
* well-formed message. The order of the repeated values will be
* preserved.
*/
PROTOBUF_C_LABEL_REPEATED,
/**
* This field has no label. This is valid only in proto3 and is
* equivalent to OPTIONAL but no "has" quantifier will be consulted.
*/
PROTOBUF_C_LABEL_NONE,
} ProtobufCLabel;
/**
* Field value types.
*
* \see [Scalar Value Types] in the Protocol Buffers documentation.
*
* [Scalar Value Types]:
* https://developers.google.com/protocol-buffers/docs/proto#scalar
*/
typedef enum {
PROTOBUF_C_TYPE_INT32, /**< int32 */
PROTOBUF_C_TYPE_SINT32, /**< signed int32 */
PROTOBUF_C_TYPE_SFIXED32, /**< signed int32 (4 bytes) */
PROTOBUF_C_TYPE_INT64, /**< int64 */
PROTOBUF_C_TYPE_SINT64, /**< signed int64 */
PROTOBUF_C_TYPE_SFIXED64, /**< signed int64 (8 bytes) */
PROTOBUF_C_TYPE_UINT32, /**< unsigned int32 */
PROTOBUF_C_TYPE_FIXED32, /**< unsigned int32 (4 bytes) */
PROTOBUF_C_TYPE_UINT64, /**< unsigned int64 */
PROTOBUF_C_TYPE_FIXED64, /**< unsigned int64 (8 bytes) */
PROTOBUF_C_TYPE_FLOAT, /**< float */
PROTOBUF_C_TYPE_DOUBLE, /**< double */
PROTOBUF_C_TYPE_BOOL, /**< boolean */
PROTOBUF_C_TYPE_ENUM, /**< enumerated type */
PROTOBUF_C_TYPE_STRING, /**< UTF-8 or ASCII string */
PROTOBUF_C_TYPE_BYTES, /**< arbitrary byte sequence */
PROTOBUF_C_TYPE_MESSAGE, /**< nested message */
} ProtobufCType;
/**
* Field wire types.
*
* \see [Message Structure] in the Protocol Buffers documentation.
*
* [Message Structure]:
* https://developers.google.com/protocol-buffers/docs/encoding#structure
*/
typedef enum {
PROTOBUF_C_WIRE_TYPE_VARINT = 0,
PROTOBUF_C_WIRE_TYPE_64BIT = 1,
PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED = 2,
/* "Start group" and "end group" wire types are unsupported. */
PROTOBUF_C_WIRE_TYPE_32BIT = 5,
} ProtobufCWireType;
struct ProtobufCAllocator;
struct ProtobufCBinaryData;
struct ProtobufCBuffer;
struct ProtobufCBufferSimple;
struct ProtobufCEnumDescriptor;
struct ProtobufCEnumValue;
struct ProtobufCEnumValueIndex;
struct ProtobufCFieldDescriptor;
struct ProtobufCIntRange;
struct ProtobufCMessage;
struct ProtobufCMessageDescriptor;
struct ProtobufCMessageUnknownField;
struct ProtobufCMethodDescriptor;
struct ProtobufCService;
struct ProtobufCServiceDescriptor;
typedef struct ProtobufCAllocator ProtobufCAllocator;
typedef struct ProtobufCBinaryData ProtobufCBinaryData;
typedef struct ProtobufCBuffer ProtobufCBuffer;
typedef struct ProtobufCBufferSimple ProtobufCBufferSimple;
typedef struct ProtobufCEnumDescriptor ProtobufCEnumDescriptor;
typedef struct ProtobufCEnumValue ProtobufCEnumValue;
typedef struct ProtobufCEnumValueIndex ProtobufCEnumValueIndex;
typedef struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
typedef struct ProtobufCIntRange ProtobufCIntRange;
typedef struct ProtobufCMessage ProtobufCMessage;
typedef struct ProtobufCMessageDescriptor ProtobufCMessageDescriptor;
typedef struct ProtobufCMessageUnknownField ProtobufCMessageUnknownField;
typedef struct ProtobufCMethodDescriptor ProtobufCMethodDescriptor;
typedef struct ProtobufCService ProtobufCService;
typedef struct ProtobufCServiceDescriptor ProtobufCServiceDescriptor;
/** Boolean type. */
typedef int protobuf_c_boolean;
typedef void (*ProtobufCClosure)(const ProtobufCMessage *, void *closure_data);
typedef void (*ProtobufCMessageInit)(ProtobufCMessage *);
typedef void (*ProtobufCServiceDestroy)(ProtobufCService *);
/**
* Structure for defining a custom memory allocator.
*/
struct ProtobufCAllocator {
/** Function to allocate memory. */
void *(*alloc)(void *allocator_data, size_t size);
/** Function to free memory. */
void (*free)(void *allocator_data, void *pointer);
/** Opaque pointer passed to `alloc` and `free` functions. */
void *allocator_data;
};
/**
* Structure for the protobuf `bytes` scalar type.
*
* The data contained in a `ProtobufCBinaryData` is an arbitrary sequence of
* bytes. It may contain embedded `NUL` characters and is not required to be
* `NUL`-terminated.
*/
struct ProtobufCBinaryData {
size_t len; /**< Number of bytes in the `data` field. */
uint8_t *data; /**< Data bytes. */
};
/**
* Structure for defining a virtual append-only buffer. Used by
* protobuf_c_message_pack_to_buffer() to abstract the consumption of serialized
* bytes.
*
* `ProtobufCBuffer` "subclasses" may be defined on the stack. For example, to
* write to a `FILE` object:
*
~~~{.c}
typedef struct {
ProtobufCBuffer base;
FILE *fp;
} BufferAppendToFile;
static void
my_buffer_file_append(ProtobufCBuffer *buffer,
size_t len,
const uint8_t *data)
{
BufferAppendToFile *file_buf = (BufferAppendToFile *) buffer;
fwrite(data, len, 1, file_buf->fp); // XXX: No error handling!
}
~~~
*
* To use this new type of ProtobufCBuffer, it could be called as follows:
*
~~~{.c}
...
BufferAppendToFile tmp = {0};
tmp.base.append = my_buffer_file_append;
tmp.fp = fp;
protobuf_c_message_pack_to_buffer(&message, &tmp);
...
~~~
*/
struct ProtobufCBuffer {
/** Append function. Consumes the `len` bytes stored at `data`. */
void (*append)(ProtobufCBuffer *buffer,
size_t len,
const uint8_t *data);
};
/**
* Simple buffer "subclass" of `ProtobufCBuffer`.
*
* A `ProtobufCBufferSimple` object is declared on the stack and uses a
* scratch buffer provided by the user for the initial allocation. It performs
* exponential resizing, using dynamically allocated memory. A
* `ProtobufCBufferSimple` object can be created and used as follows:
*
~~~{.c}
uint8_t pad[128];
ProtobufCBufferSimple simple = PROTOBUF_C_BUFFER_SIMPLE_INIT(pad);
ProtobufCBuffer *buffer = (ProtobufCBuffer *) &simple;
~~~
*
* `buffer` can now be used with `protobuf_c_message_pack_to_buffer()`. Once a
* message has been serialized to a `ProtobufCBufferSimple` object, the
* serialized data bytes can be accessed from the `.data` field.
*
* To free the memory allocated by a `ProtobufCBufferSimple` object, if any,
* call PROTOBUF_C_BUFFER_SIMPLE_CLEAR() on the object, for example:
*
~~~{.c}
PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&simple);
~~~
*
* \see PROTOBUF_C_BUFFER_SIMPLE_INIT
* \see PROTOBUF_C_BUFFER_SIMPLE_CLEAR
*/
struct ProtobufCBufferSimple {
/** "Base class". */
ProtobufCBuffer base;
/** Number of bytes allocated in `data`. */
size_t alloced;
/** Number of bytes currently stored in `data`. */
size_t len;
/** Data bytes. */
uint8_t *data;
/** Whether `data` must be freed. */
protobuf_c_boolean must_free_data;
/** Allocator to use. May be NULL to indicate the system allocator. */
ProtobufCAllocator *allocator;
};
/**
* Describes an enumeration as a whole, with all of its values.
*/
struct ProtobufCEnumDescriptor {
/** Magic value checked to ensure that the API is used correctly. */
uint32_t magic;
/** The qualified name (e.g., "namespace.Type"). */
const char *name;
/** The unqualified name as given in the .proto file (e.g., "Type"). */
const char *short_name;
/** Identifier used in generated C code. */
const char *c_name;
/** The dot-separated namespace. */
const char *package_name;
/** Number elements in `values`. */
unsigned n_values;
/** Array of distinct values, sorted by numeric value. */
const ProtobufCEnumValue *values;
/** Number of elements in `values_by_name`. */
unsigned n_value_names;
/** Array of named values, including aliases, sorted by name. */
const ProtobufCEnumValueIndex *values_by_name;
/** Number of elements in `value_ranges`. */
unsigned n_value_ranges;
/** Value ranges, for faster lookups by numeric value. */
const ProtobufCIntRange *value_ranges;
/** Reserved for future use. */
void *reserved1;
/** Reserved for future use. */
void *reserved2;
/** Reserved for future use. */
void *reserved3;
/** Reserved for future use. */
void *reserved4;
};
/**
* Represents a single value of an enumeration.
*/
struct ProtobufCEnumValue {
/** The string identifying this value in the .proto file. */
const char *name;
/** The string identifying this value in generated C code. */
const char *c_name;
/** The numeric value assigned in the .proto file. */
int value;
};
/**
* Used by `ProtobufCEnumDescriptor` to look up enum values.
*/
struct ProtobufCEnumValueIndex {
/** Name of the enum value. */
const char *name;
/** Index into values[] array. */
unsigned index;
};
/**
* Describes a single field in a message.
*/
struct ProtobufCFieldDescriptor {
/** Name of the field as given in the .proto file. */
const char *name;
/** Tag value of the field as given in the .proto file. */
uint32_t id;
/** Whether the field is `REQUIRED`, `OPTIONAL`, or `REPEATED`. */
ProtobufCLabel label;
/** The type of the field. */
ProtobufCType type;
/**
* The offset in bytes of the message's C structure's quantifier field
* (the `has_MEMBER` field for optional members or the `n_MEMBER` field
* for repeated members or the case enum for oneofs).
*/
unsigned quantifier_offset;
/**
* The offset in bytes into the message's C structure for the member
* itself.
*/
unsigned offset;
/**
* A type-specific descriptor.
*
* If `type` is `PROTOBUF_C_TYPE_ENUM`, then `descriptor` points to the
* corresponding `ProtobufCEnumDescriptor`.
*
* If `type` is `PROTOBUF_C_TYPE_MESSAGE`, then `descriptor` points to
* the corresponding `ProtobufCMessageDescriptor`.
*
* Otherwise this field is NULL.
*/
const void *descriptor; /* for MESSAGE and ENUM types */
/** The default value for this field, if defined. May be NULL. */
const void *default_value;
/**
* A flag word. Zero or more of the bits defined in the
* `ProtobufCFieldFlag` enum may be set.
*/
uint32_t flags;
/** Reserved for future use. */
unsigned reserved_flags;
/** Reserved for future use. */
void *reserved2;
/** Reserved for future use. */
void *reserved3;
};
/**
* Helper structure for optimizing int => index lookups in the case
* where the keys are mostly consecutive values, as they presumably are for
* enums and fields.
*
* The data structures requires that the values in the original array are
* sorted.
*/
struct ProtobufCIntRange {
int start_value;
unsigned orig_index;
/*
* NOTE: the number of values in the range can be inferred by looking
* at the next element's orig_index. A dummy element is added to make
* this simple.
*/
};
/**
* An instance of a message.
*
* `ProtobufCMessage` is a light-weight "base class" for all messages.
*
* In particular, `ProtobufCMessage` doesn't have any allocation policy
* associated with it. That's because it's common to create `ProtobufCMessage`
* objects on the stack. In fact, that's what we recommend for sending messages.
* If the object is allocated from the stack, you can't really have a memory
* leak.
*
* This means that calls to functions like protobuf_c_message_unpack() which
* return a `ProtobufCMessage` must be paired with a call to a free function,
* like protobuf_c_message_free_unpacked().
*/
struct ProtobufCMessage {
/** The descriptor for this message type. */
const ProtobufCMessageDescriptor *descriptor;
/** The number of elements in `unknown_fields`. */
unsigned n_unknown_fields;
/** The fields that weren't recognized by the parser. */
ProtobufCMessageUnknownField *unknown_fields;
};
/**
* Describes a message.
*/
struct ProtobufCMessageDescriptor {
/** Magic value checked to ensure that the API is used correctly. */
uint32_t magic;
/** The qualified name (e.g., "namespace.Type"). */
const char *name;
/** The unqualified name as given in the .proto file (e.g., "Type"). */
const char *short_name;
/** Identifier used in generated C code. */
const char *c_name;
/** The dot-separated namespace. */
const char *package_name;
/**
* Size in bytes of the C structure representing an instance of this
* type of message.
*/
size_t sizeof_message;
/** Number of elements in `fields`. */
unsigned n_fields;
/** Field descriptors, sorted by tag number. */
const ProtobufCFieldDescriptor *fields;
/** Used for looking up fields by name. */
const unsigned *fields_sorted_by_name;
/** Number of elements in `field_ranges`. */
unsigned n_field_ranges;
/** Used for looking up fields by id. */
const ProtobufCIntRange *field_ranges;
/** Message initialisation function. */
ProtobufCMessageInit message_init;
/** Reserved for future use. */
void *reserved1;
/** Reserved for future use. */
void *reserved2;
/** Reserved for future use. */
void *reserved3;
};
/**
* An unknown message field.
*/
struct ProtobufCMessageUnknownField {
/** The tag number. */
uint32_t tag;
/** The wire type of the field. */
ProtobufCWireType wire_type;
/** Number of bytes in `data`. */
size_t len;
/** Field data. */
uint8_t *data;
};
/**
* Method descriptor.
*/
struct ProtobufCMethodDescriptor {
/** Method name. */
const char *name;
/** Input message descriptor. */
const ProtobufCMessageDescriptor *input;
/** Output message descriptor. */
const ProtobufCMessageDescriptor *output;
};
/**
* Service.
*/
struct ProtobufCService {
/** Service descriptor. */
const ProtobufCServiceDescriptor *descriptor;
/** Function to invoke the service. */
void (*invoke)(ProtobufCService *service,
unsigned method_index,
const ProtobufCMessage *input,
ProtobufCClosure closure,
void *closure_data);
/** Function to destroy the service. */
void (*destroy)(ProtobufCService *service);
};
/**
* Service descriptor.
*/
struct ProtobufCServiceDescriptor {
/** Magic value checked to ensure that the API is used correctly. */
uint32_t magic;
/** Service name. */
const char *name;
/** Short version of service name. */
const char *short_name;
/** C identifier for the service name. */
const char *c_name;
/** Package name. */
const char *package;
/** Number of elements in `methods`. */
unsigned n_methods;
/** Method descriptors, in the order defined in the .proto file. */
const ProtobufCMethodDescriptor *methods;
/** Sort index of methods. */
const unsigned *method_indices_by_name;
};
/**
* Get the version of the protobuf-c library. Note that this is the version of
* the library linked against, not the version of the headers compiled against.
*
* \return A string containing the version number of protobuf-c.
*/
PROTOBUF_C__API
const char *
protobuf_c_version(void);
/**
* Get the version of the protobuf-c library. Note that this is the version of
* the library linked against, not the version of the headers compiled against.
*
* \return A 32 bit unsigned integer containing the version number of
* protobuf-c, represented in base-10 as (MAJOR*1E6) + (MINOR*1E3) + PATCH.
*/
PROTOBUF_C__API
uint32_t
protobuf_c_version_number(void);
/**
* The version of the protobuf-c headers, represented as a string using the same
* format as protobuf_c_version().
*/
#define PROTOBUF_C_VERSION "1.4.1"
/**
* The version of the protobuf-c headers, represented as an integer using the
* same format as protobuf_c_version_number().
*/
#define PROTOBUF_C_VERSION_NUMBER 1004001
/**
* The minimum protoc-c version which works with the current version of the
* protobuf-c headers.
*/
#define PROTOBUF_C_MIN_COMPILER_VERSION 1000000
/**
* Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by name.
*
* \param desc
* The `ProtobufCEnumDescriptor` object.
* \param name
* The `name` field from the corresponding `ProtobufCEnumValue` object to
* match.
* \return
* A `ProtobufCEnumValue` object.
* \retval NULL
* If not found or if the optimize_for = CODE_SIZE option was set.
*/
PROTOBUF_C__API
const ProtobufCEnumValue *
protobuf_c_enum_descriptor_get_value_by_name(
const ProtobufCEnumDescriptor *desc,
const char *name);
/**
* Look up a `ProtobufCEnumValue` from a `ProtobufCEnumDescriptor` by numeric
* value.
*
* \param desc
* The `ProtobufCEnumDescriptor` object.
* \param value
* The `value` field from the corresponding `ProtobufCEnumValue` object to
* match.
*
* \return
* A `ProtobufCEnumValue` object.
* \retval NULL
* If not found.
*/
PROTOBUF_C__API
const ProtobufCEnumValue *
protobuf_c_enum_descriptor_get_value(
const ProtobufCEnumDescriptor *desc,
int value);
/**
* Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
* the name of the field.
*
* \param desc
* The `ProtobufCMessageDescriptor` object.
* \param name
* The name of the field.
* \return
* A `ProtobufCFieldDescriptor` object.
* \retval NULL
* If not found or if the optimize_for = CODE_SIZE option was set.
*/
PROTOBUF_C__API
const ProtobufCFieldDescriptor *
protobuf_c_message_descriptor_get_field_by_name(
const ProtobufCMessageDescriptor *desc,
const char *name);
/**
* Look up a `ProtobufCFieldDescriptor` from a `ProtobufCMessageDescriptor` by
* the tag value of the field.
*
* \param desc
* The `ProtobufCMessageDescriptor` object.
* \param value
* The tag value of the field.
* \return
* A `ProtobufCFieldDescriptor` object.
* \retval NULL
* If not found.
*/
PROTOBUF_C__API
const ProtobufCFieldDescriptor *
protobuf_c_message_descriptor_get_field(
const ProtobufCMessageDescriptor *desc,
unsigned value);
/**
* Determine the number of bytes required to store the serialised message.
*
* \param message
* The message object to serialise.
* \return
* Number of bytes.
*/
PROTOBUF_C__API
size_t
protobuf_c_message_get_packed_size(const ProtobufCMessage *message);
/**
* Serialise a message from its in-memory representation.
*
* This function stores the serialised bytes of the message in a pre-allocated
* buffer.
*
* \param message
* The message object to serialise.
* \param[out] out
* Buffer to store the bytes of the serialised message. This buffer must
* have enough space to store the packed message. Use
* protobuf_c_message_get_packed_size() to determine the number of bytes
* required.
* \return
* Number of bytes stored in `out`.
*/
PROTOBUF_C__API
size_t
protobuf_c_message_pack(const ProtobufCMessage *message, uint8_t *out);
/**
* Serialise a message from its in-memory representation to a virtual buffer.
*
* This function calls the `append` method of a `ProtobufCBuffer` object to
* consume the bytes generated by the serialiser.
*
* \param message
* The message object to serialise.
* \param buffer
* The virtual buffer object.
* \return
* Number of bytes passed to the virtual buffer.
*/
PROTOBUF_C__API
size_t
protobuf_c_message_pack_to_buffer(
const ProtobufCMessage *message,
ProtobufCBuffer *buffer);
/**
* Unpack a serialised message into an in-memory representation.
*
* \param descriptor
* The message descriptor.
* \param allocator
* `ProtobufCAllocator` to use for memory allocation. May be NULL to
* specify the default allocator.
* \param len
* Length in bytes of the serialised message.
* \param data
* Pointer to the serialised message.
* \return
* An unpacked message object.
* \retval NULL
* If an error occurred during unpacking.
*/
PROTOBUF_C__API
ProtobufCMessage *
protobuf_c_message_unpack(
const ProtobufCMessageDescriptor *descriptor,
ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
/**
* Free an unpacked message object.
*
* This function should be used to deallocate the memory used by a call to
* protobuf_c_message_unpack().
*
* \param message
* The message object to free. May be NULL.
* \param allocator
* `ProtobufCAllocator` to use for memory deallocation. May be NULL to
* specify the default allocator.
*/
PROTOBUF_C__API
void
protobuf_c_message_free_unpacked(
ProtobufCMessage *message,
ProtobufCAllocator *allocator);
/**
* Check the validity of a message object.
*
* Makes sure all required fields (`PROTOBUF_C_LABEL_REQUIRED`) are present.
* Recursively checks nested messages.
*
* \retval TRUE
* Message is valid.
* \retval FALSE
* Message is invalid.
*/
PROTOBUF_C__API
protobuf_c_boolean
protobuf_c_message_check(const ProtobufCMessage *);
/** Message initialiser. */
#define PROTOBUF_C_MESSAGE_INIT(descriptor) { descriptor, 0, NULL }
/**
* Initialise a message object from a message descriptor.
*
* \param descriptor
* Message descriptor.
* \param message
* Allocated block of memory of size `descriptor->sizeof_message`.
*/
PROTOBUF_C__API
void
protobuf_c_message_init(
const ProtobufCMessageDescriptor *descriptor,
void *message);
/**
* Free a service.
*
* \param service
* The service object to free.
*/
PROTOBUF_C__API
void
protobuf_c_service_destroy(ProtobufCService *service);
/**
* Look up a `ProtobufCMethodDescriptor` by name.
*
* \param desc
* Service descriptor.
* \param name
* Name of the method.
*
* \return
* A `ProtobufCMethodDescriptor` object.
* \retval NULL
* If not found or if the optimize_for = CODE_SIZE option was set.
*/
PROTOBUF_C__API
const ProtobufCMethodDescriptor *
protobuf_c_service_descriptor_get_method_by_name(
const ProtobufCServiceDescriptor *desc,
const char *name);
/**
* Initialise a `ProtobufCBufferSimple` object.
*/
#define PROTOBUF_C_BUFFER_SIMPLE_INIT(array_of_bytes) \
{ \
{ protobuf_c_buffer_simple_append }, \
sizeof(array_of_bytes), \
0, \
(array_of_bytes), \
0, \
NULL \
}
/**
* Clear a `ProtobufCBufferSimple` object, freeing any allocated memory.
*/
#define PROTOBUF_C_BUFFER_SIMPLE_CLEAR(simp_buf) \
do { \
if ((simp_buf)->must_free_data) { \
if ((simp_buf)->allocator != NULL) \
(simp_buf)->allocator->free( \
(simp_buf)->allocator, \
(simp_buf)->data); \
else \
free((simp_buf)->data); \
} \
} while (0)
/**
* The `append` method for `ProtobufCBufferSimple`.
*
* \param buffer
* The buffer object to append to. Must actually be a
* `ProtobufCBufferSimple` object.
* \param len
* Number of bytes in `data`.
* \param data
* Data to append.
*/
PROTOBUF_C__API
void
protobuf_c_buffer_simple_append(
ProtobufCBuffer *buffer,
size_t len,
const unsigned char *data);
PROTOBUF_C__API
void
protobuf_c_service_generated_init(
ProtobufCService *service,
const ProtobufCServiceDescriptor *descriptor,
ProtobufCServiceDestroy destroy);
PROTOBUF_C__API
void
protobuf_c_service_invoke_internal(
ProtobufCService *service,
unsigned method_index,
const ProtobufCMessage *input,
ProtobufCClosure closure,
void *closure_data);
/**@}*/
PROTOBUF_C__END_DECLS
#endif /* PROTOBUF_C_H */