1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-18 10:04:04 +03:00
systemd/src/shared/varlink-idl.h
2023-10-14 17:40:07 +02:00

159 lines
7.3 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include "json.h"
#include "macro.h"
/* 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. */
typedef enum VarlinkSymbolType {
VARLINK_ENUM_TYPE,
VARLINK_STRUCT_TYPE,
VARLINK_METHOD,
VARLINK_ERROR,
_VARLINK_SYMBOL_TYPE_MAX,
_VARLINK_SYMBOL_TYPE_INVALID = -EINVAL,
} VarlinkSymbolType;
typedef enum VarlinkFieldType {
_VARLINK_FIELD_TYPE_END_MARKER = 0, /* zero type means: this is the last entry in the fields[] array of VarlinkSymbol */
VARLINK_STRUCT,
VARLINK_ENUM,
VARLINK_NAMED_TYPE,
VARLINK_BOOL,
VARLINK_INT,
VARLINK_FLOAT,
VARLINK_STRING,
VARLINK_OBJECT,
VARLINK_ENUM_VALUE,
_VARLINK_FIELD_TYPE_MAX,
_VARLINK_FIELD_TYPE_INVALID = -EINVAL,
} VarlinkFieldType;
typedef enum VarlinkFieldDirection {
VARLINK_REGULAR,
VARLINK_INPUT,
VARLINK_OUTPUT,
_VARLINK_FIELD_DIRECTION_MAX,
_VARLINK_FIELD_DIRECTION_INVALID = -EINVAL,
} VarlinkFieldDirection;
typedef enum VarlinkFieldFlags {
VARLINK_ARRAY = 1 << 0,
VARLINK_MAP = 1 << 1,
VARLINK_NULLABLE = 1 << 2,
_VARLINK_FIELD_FLAGS_MAX = (1 << 3) - 1,
_VARLINK_FIELD_FLAGS_INVALID = -EINVAL,
} VarlinkFieldFlags;
typedef struct VarlinkField VarlinkField;
typedef struct VarlinkSymbol VarlinkSymbol;
typedef struct VarlinkInterface VarlinkInterface;
/* Fields are the components making up symbols */
struct VarlinkField {
const char *name;
VarlinkFieldType field_type;
VarlinkFieldFlags field_flags;
VarlinkFieldDirection field_direction; /* in case of method call fields: whether input or output argument */
const VarlinkSymbol *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 VarlinkSymbol {
const char *name; /* most symbols have a name, but sometimes they are created on-the-fly for fields, in which case they are anonymous */
VarlinkSymbolType symbol_type;
VarlinkField fields[];
};
/* An interface definition has a name and consist of symbols */
struct VarlinkInterface {
const char *name;
const VarlinkSymbol *symbols[];
};
#define VARLINK_DEFINE_FIELD(_name, _field_type, _field_flags) \
{ .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags) }
#define VARLINK_DEFINE_FIELD_BY_TYPE(_name, _named_type, _field_flags) \
{ .name = #_name, .field_type = VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags) }
#define VARLINK_DEFINE_INPUT(_name, _field_type, _field_flags) \
{ .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags), .field_direction = VARLINK_INPUT }
#define VARLINK_DEFINE_INPUT_BY_TYPE(_name, _named_type, _field_flags) \
{ .name = #_name, .field_type = VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags), .field_direction = VARLINK_INPUT }
#define VARLINK_DEFINE_OUTPUT(_name, _field_type, _field_flags) \
{ .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags), .field_direction = VARLINK_OUTPUT }
#define VARLINK_DEFINE_OUTPUT_BY_TYPE(_name, _named_type, _field_flags) \
{ .name = #_name, .field_type = VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags), .field_direction = VARLINK_OUTPUT }
#define VARLINK_DEFINE_ENUM_VALUE(_name) \
{ .name = #_name, .field_type = VARLINK_ENUM_VALUE }
#define VARLINK_DEFINE_METHOD(_name, ...) \
const VarlinkSymbol vl_method_ ## _name = { \
.name = #_name, \
.symbol_type = VARLINK_METHOD, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define VARLINK_DEFINE_ERROR(_name, ...) \
const VarlinkSymbol vl_error_ ## _name = { \
.name = #_name, \
.symbol_type = VARLINK_ERROR, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define VARLINK_DEFINE_STRUCT_TYPE(_name, ...) \
const VarlinkSymbol vl_type_ ## _name = { \
.name = #_name, \
.symbol_type = VARLINK_STRUCT_TYPE, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define VARLINK_DEFINE_ENUM_TYPE(_name, ...) \
const VarlinkSymbol vl_type_ ## _name = { \
.name = #_name, \
.symbol_type = VARLINK_ENUM_TYPE, \
.fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \
}
#define VARLINK_DEFINE_INTERFACE(_name, _full_name, ...) \
const VarlinkInterface vl_interface_ ## _name = { \
.name = (_full_name), \
.symbols = { __VA_ARGS__ __VA_OPT__(,) NULL}, \
}
int varlink_idl_dump(FILE *f, int use_colors, const VarlinkInterface *interface);
int varlink_idl_format(const VarlinkInterface *interface, char **ret);
int varlink_idl_parse(const char *text, unsigned *ret_line, unsigned *ret_column, VarlinkInterface **ret);
VarlinkInterface* varlink_interface_free(VarlinkInterface *interface);
DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkInterface*, varlink_interface_free);
bool varlink_idl_field_name_is_valid(const char *name);
bool varlink_idl_symbol_name_is_valid(const char *name);
bool varlink_idl_interface_name_is_valid(const char *name);
int varlink_idl_consistent(const VarlinkInterface *interface, int level);
const VarlinkSymbol* varlink_idl_find_symbol(const VarlinkInterface *interface, VarlinkSymbolType type, const char *name);
const VarlinkField* varlink_idl_find_field(const VarlinkSymbol *symbol, const char *name);
int varlink_idl_validate_method_call(const VarlinkSymbol *method, JsonVariant *v, const char **bad_field);
int varlink_idl_validate_method_reply(const VarlinkSymbol *method, JsonVariant *v, const char **bad_field);
int varlink_idl_validate_error(const VarlinkSymbol *error, JsonVariant *v, const char **bad_field);