/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef foosdvarlinkidlhfoo
#define foosdvarlinkidlhfoo
/***
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see .
***/
#include
#include "_sd-common.h"
#include "sd-json.h"
_SD_BEGIN_DECLARATIONS;
/* This implements the Varlink Interface Definition Language ("Varlink IDL"),
* i.e. https://varlink.org/Interface-Definition
*
* Primarily allows encoding static interface definitions in C code, that can be converted to the textual IDL
* format on-the-fly. Can also parse the textual format back to C structures. Validates the interface
* definitions for internal consistency and validates JSON objects against the interface definitions. */
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_interface_flags_t) {
_SD_VARLINK_INTERFACE_FLAGS_MAX = (1 << 0) - 1,
_SD_VARLINK_INTERFACE_FLAGS_INVALID = -EINVAL,
_SD_ENUM_FORCE_S64(SD_VARLINK_INTERFACE_FLAGS)
} sd_varlink_interface_flags_t;
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_symbol_type_t) {
SD_VARLINK_ENUM_TYPE,
SD_VARLINK_STRUCT_TYPE,
SD_VARLINK_METHOD,
SD_VARLINK_ERROR,
_SD_VARLINK_INTERFACE_COMMENT, /* Not really a symbol, just a comment about the interface */
_SD_VARLINK_SYMBOL_COMMENT, /* Not really a symbol, just a comment about a symbol */
_SD_VARLINK_SYMBOL_TYPE_MAX,
_SD_VARLINK_SYMBOL_TYPE_INVALID = -EINVAL,
_SD_ENUM_FORCE_S64(SD_VARLINK_SYMBOL)
} sd_varlink_symbol_type_t;
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_symbol_flags_t) {
SD_VARLINK_SUPPORTS_MORE = 1 << 0, /* Call supports "more" flag */
SD_VARLINK_REQUIRES_MORE = 1 << 1, /* Call requires "more" flag */
_SD_VARLINK_SYMBOL_FLAGS_MAX = (1 << 2) - 1,
_SD_VARLINK_SYMBOL_FLAGS_INVALID = -EINVAL,
_SD_ENUM_FORCE_S64(SD_VARLINK_SYMBOL_FLAGS)
} sd_varlink_symbol_flags_t;
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_field_type_t) {
_SD_VARLINK_FIELD_TYPE_END_MARKER = 0, /* zero type means: this is the last entry in the fields[] array of sd_varlink_symbol */
SD_VARLINK_STRUCT,
SD_VARLINK_ENUM,
SD_VARLINK_NAMED_TYPE,
SD_VARLINK_BOOL,
SD_VARLINK_INT,
SD_VARLINK_FLOAT,
SD_VARLINK_STRING,
SD_VARLINK_OBJECT,
SD_VARLINK_ENUM_VALUE,
_SD_VARLINK_FIELD_COMMENT, /* Not really a field, just a comment about a field */
_SD_VARLINK_FIELD_TYPE_MAX,
_SD_VARLINK_FIELD_TYPE_INVALID = -EINVAL,
_SD_ENUM_FORCE_S64(SD_VARLINK_FIELD)
} sd_varlink_field_type_t;
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_field_direction_t) {
SD_VARLINK_REGULAR,
SD_VARLINK_INPUT,
SD_VARLINK_OUTPUT,
_SD_VARLINK_FIELD_DIRECTION_MAX,
_SD_VARLINK_FIELD_DIRECTION_INVALID = -EINVAL,
_SD_ENUM_FORCE_S64(SD_VARLINK_FIELD_DIRECTION)
} sd_varlink_field_direction_t;
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_field_flags_t) {
SD_VARLINK_ARRAY = 1 << 0,
SD_VARLINK_MAP = 1 << 1,
SD_VARLINK_NULLABLE = 1 << 2,
_SD_VARLINK_FIELD_FLAGS_MAX = (1 << 3) - 1,
_SD_VARLINK_FIELD_FLAGS_INVALID = -EINVAL,
_SD_ENUM_FORCE_S64(SD_VARLINK_FIELD_FLAGS)
} sd_varlink_field_flags_t;
typedef struct sd_varlink_field sd_varlink_field;
typedef struct sd_varlink_symbol sd_varlink_symbol;
typedef struct sd_varlink_interface sd_varlink_interface;
/* Fields are the components making up symbols */
struct sd_varlink_field {
const char *name;
sd_varlink_field_type_t field_type;
sd_varlink_field_flags_t field_flags;
sd_varlink_field_direction_t field_direction; /* in case of method call fields: whether input or output argument */
const sd_varlink_symbol *symbol; /* VARLINK_STRUCT, VARLINK_ENUM: anonymous symbol that carries the definitions, VARLINK_NAMED_TYPE: resolved symbol */
const char *named_type; /* VARLINK_NAMED_TYPE */
};
/* Symbols are primary named concepts in an interface, and are methods, errors or named types (either enum or struct). */
struct sd_varlink_symbol {
const char *name; /* most symbols have a name, but sometimes they are created on-the-fly for fields, in which case they are anonymous */
sd_varlink_symbol_type_t symbol_type;
sd_varlink_symbol_flags_t symbol_flags;
#if __STDC_VERSION__ >= 199901L
sd_varlink_field fields[];
#else
sd_varlink_field fields[1];
#endif
};
/* An interface definition has a name and consist of symbols */
struct sd_varlink_interface {
const char *name;
sd_varlink_interface_flags_t interface_flags;
#if __STDC_VERSION__ >= 199901L
const sd_varlink_symbol *symbols[];
#else
const sd_varlink_symbol *symbols[1];
#endif
};
#define SD_VARLINK_DEFINE_FIELD(_name, _field_type, _field_flags) \
{ .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags) }
#define SD_VARLINK_DEFINE_FIELD_BY_TYPE(_name, _named_type, _field_flags) \
{ .name = #_name, .field_type = SD_VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags) }
#define SD_VARLINK_DEFINE_INPUT(_name, _field_type, _field_flags) \
{ .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags), .field_direction = SD_VARLINK_INPUT }
#define SD_VARLINK_DEFINE_INPUT_BY_TYPE(_name, _named_type, _field_flags) \
{ .name = #_name, .field_type = SD_VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags), .field_direction = SD_VARLINK_INPUT }
#define SD_VARLINK_DEFINE_OUTPUT(_name, _field_type, _field_flags) \
{ .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags), .field_direction = SD_VARLINK_OUTPUT }
#define SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(_name, _named_type, _field_flags) \
{ .name = #_name, .field_type = SD_VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags), .field_direction = SD_VARLINK_OUTPUT }
#define SD_VARLINK_DEFINE_ENUM_VALUE(_name) \
{ .name = #_name, .field_type = SD_VARLINK_ENUM_VALUE }
#define SD_VARLINK_FIELD_COMMENT(text) \
{ .name = "" text, .field_type = _SD_VARLINK_FIELD_COMMENT }
/* C++ older than C20+ does not support __VA_OPT__(), but we really need it here. */
#if (defined(__STDC_VERSION__) && ((__STDC_VERSION__ >= 202311L) || defined(_GNU_SOURCE))) || (defined(__cplusplus) && (__cplusplus >= 202002L))
#define SD_VARLINK_DEFINE_METHOD(_name, ...) \
const sd_varlink_symbol vl_method_ ## _name = { \
.name = #_name, \
.symbol_type = SD_VARLINK_METHOD, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define SD_VARLINK_DEFINE_METHOD_FULL(_name, _flags, ...) \
const sd_varlink_symbol vl_method_ ## _name = { \
.name = #_name, \
.symbol_type = SD_VARLINK_METHOD, \
.symbol_flags = _flags, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define SD_VARLINK_DEFINE_ERROR(_name, ...) \
const sd_varlink_symbol vl_error_ ## _name = { \
.name = #_name, \
.symbol_type = SD_VARLINK_ERROR, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define SD_VARLINK_DEFINE_STRUCT_TYPE(_name, ...) \
const sd_varlink_symbol vl_type_ ## _name = { \
.name = #_name, \
.symbol_type = SD_VARLINK_STRUCT_TYPE, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define SD_VARLINK_DEFINE_ENUM_TYPE(_name, ...) \
const sd_varlink_symbol vl_type_ ## _name = { \
.name = #_name, \
.symbol_type = SD_VARLINK_ENUM_TYPE, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define SD_VARLINK_DEFINE_INTERFACE(_name, _full_name, ...) \
const sd_varlink_interface vl_interface_ ## _name = { \
.name = (_full_name), \
.symbols = { __VA_ARGS__ __VA_OPT__(,) NULL}, \
}
#endif
#define SD_VARLINK_SYMBOL_COMMENT(text) \
&(const sd_varlink_symbol) { \
.name = "" text, \
.symbol_type = _SD_VARLINK_SYMBOL_COMMENT, \
}
#define SD_VARLINK_INTERFACE_COMMENT(text) \
&(const sd_varlink_symbol) { \
.name = "" text, \
.symbol_type = _SD_VARLINK_INTERFACE_COMMENT, \
}
__extension__ typedef enum _SD_ENUM_TYPE_S64(sd_varlink_idl_format_flags_t) {
SD_VARLINK_IDL_FORMAT_COLOR = 1 << 0,
SD_VARLINK_IDL_FORMAT_COLOR_AUTO = 1 << 1,
_SD_ENUM_FORCE_S64(SD_VARLINK_IDL_FORMAT)
} sd_varlink_idl_format_flags_t;
int sd_varlink_idl_dump(FILE *f, const sd_varlink_interface *interface, sd_varlink_idl_format_flags_t flags, size_t cols);
int sd_varlink_idl_format_full(const sd_varlink_interface *interface, sd_varlink_idl_format_flags_t flags, size_t cols, char **ret);
int sd_varlink_idl_format(const sd_varlink_interface *interface, char **ret);
int sd_varlink_idl_parse(const char *text, unsigned *reterr_line, unsigned *reterr_column, sd_varlink_interface **ret);
sd_varlink_interface* sd_varlink_interface_free(sd_varlink_interface *interface);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_varlink_interface, sd_varlink_interface_free);
_SD_END_DECLARATIONS;
#endif