]>
Commit | Line | Data |
---|---|---|
e50b2a93 LP |
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | #pragma once | |
3 | ||
4 | #include <errno.h> | |
5 | #include <stdbool.h> | |
6 | #include <stdio.h> | |
7 | ||
8 | #include "json.h" | |
9 | #include "macro.h" | |
10 | ||
11 | /* This implements the Varlink Interface Definition Language ("Varlink IDL"), | |
12 | * i.e. https://varlink.org/Interface-Definition | |
13 | * | |
14 | * Primarily allows encoding static interface definitions in C code, that can be converted to the textual IDL | |
15 | * format on-the-fly. Can also parse the textual format back to C structures. Validates the interface | |
16 | * definitions for internal consistency and validates JSON objects against the interface definitions. */ | |
17 | ||
18 | typedef enum VarlinkSymbolType { | |
19 | VARLINK_ENUM_TYPE, | |
20 | VARLINK_STRUCT_TYPE, | |
21 | VARLINK_METHOD, | |
22 | VARLINK_ERROR, | |
23 | _VARLINK_SYMBOL_TYPE_MAX, | |
24 | _VARLINK_SYMBOL_TYPE_INVALID = -EINVAL, | |
25 | } VarlinkSymbolType; | |
26 | ||
27 | typedef enum VarlinkFieldType { | |
28 | _VARLINK_FIELD_TYPE_END_MARKER = 0, /* zero type means: this is the last entry in the fields[] array of VarlinkSymbol */ | |
29 | VARLINK_STRUCT, | |
30 | VARLINK_ENUM, | |
31 | VARLINK_NAMED_TYPE, | |
32 | VARLINK_BOOL, | |
33 | VARLINK_INT, | |
34 | VARLINK_FLOAT, | |
35 | VARLINK_STRING, | |
36 | VARLINK_OBJECT, | |
37 | VARLINK_ENUM_VALUE, | |
38 | _VARLINK_FIELD_TYPE_MAX, | |
39 | _VARLINK_FIELD_TYPE_INVALID = -EINVAL, | |
40 | } VarlinkFieldType; | |
41 | ||
42 | typedef enum VarlinkFieldDirection { | |
43 | VARLINK_REGULAR, | |
44 | VARLINK_INPUT, | |
45 | VARLINK_OUTPUT, | |
46 | _VARLINK_FIELD_DIRECTION_MAX, | |
47 | _VARLINK_FIELD_DIRECTION_INVALID = -EINVAL, | |
48 | } VarlinkFieldDirection; | |
49 | ||
50 | typedef enum VarlinkFieldFlags { | |
51 | VARLINK_ARRAY = 1 << 0, | |
52 | VARLINK_MAP = 1 << 1, | |
53 | VARLINK_NULLABLE = 1 << 2, | |
54 | _VARLINK_FIELD_FLAGS_MAX = (1 << 3) - 1, | |
55 | _VARLINK_FIELD_FLAGS_INVALID = -EINVAL, | |
56 | } VarlinkFieldFlags; | |
57 | ||
58 | typedef struct VarlinkField VarlinkField; | |
59 | typedef struct VarlinkSymbol VarlinkSymbol; | |
60 | typedef struct VarlinkInterface VarlinkInterface; | |
61 | ||
62 | /* Fields are the components making up symbols */ | |
63 | struct VarlinkField { | |
64 | const char *name; | |
65 | VarlinkFieldType field_type; | |
66 | VarlinkFieldFlags field_flags; | |
67 | VarlinkFieldDirection field_direction; /* in case of method call fields: whether input or output argument */ | |
68 | const VarlinkSymbol *symbol; /* VARLINK_STRUCT, VARLINK_ENUM: anonymous symbol that carries the definitions, VARLINK_NAMED_TYPE: resolved symbol */ | |
69 | const char *named_type; /* VARLINK_NAMED_TYPE */ | |
70 | }; | |
71 | ||
72 | /* Symbols are primary named concepts in an interface, and are methods, errors or named types (either enum or struct). */ | |
73 | struct VarlinkSymbol { | |
74 | const char *name; /* most symbols have a name, but sometimes they are created on-the-fly for fields, in which case they are anonymous */ | |
75 | VarlinkSymbolType symbol_type; | |
76 | VarlinkField fields[]; | |
77 | }; | |
78 | ||
79 | /* An interface definition has a name and consist of symbols */ | |
80 | struct VarlinkInterface { | |
81 | const char *name; | |
82 | const VarlinkSymbol *symbols[]; | |
83 | }; | |
84 | ||
85 | #define VARLINK_DEFINE_FIELD(_name, _field_type, _field_flags) \ | |
86 | { .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags) } | |
87 | ||
88 | #define VARLINK_DEFINE_FIELD_BY_TYPE(_name, _named_type, _field_flags) \ | |
89 | { .name = #_name, .field_type = VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags) } | |
90 | ||
91 | #define VARLINK_DEFINE_INPUT(_name, _field_type, _field_flags) \ | |
92 | { .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags), .field_direction = VARLINK_INPUT } | |
93 | ||
94 | #define VARLINK_DEFINE_INPUT_BY_TYPE(_name, _named_type, _field_flags) \ | |
95 | { .name = #_name, .field_type = VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags), .field_direction = VARLINK_INPUT } | |
96 | ||
97 | #define VARLINK_DEFINE_OUTPUT(_name, _field_type, _field_flags) \ | |
98 | { .name = #_name, .field_type = (_field_type), .field_flags = (_field_flags), .field_direction = VARLINK_OUTPUT } | |
99 | ||
100 | #define VARLINK_DEFINE_OUTPUT_BY_TYPE(_name, _named_type, _field_flags) \ | |
101 | { .name = #_name, .field_type = VARLINK_NAMED_TYPE, .named_type = #_named_type, .symbol = &vl_type_ ## _named_type, .field_flags = (_field_flags), .field_direction = VARLINK_OUTPUT } | |
102 | ||
103 | #define VARLINK_DEFINE_ENUM_VALUE(_name) \ | |
104 | { .name = #_name, .field_type = VARLINK_ENUM_VALUE } | |
105 | ||
106 | #define VARLINK_DEFINE_METHOD(_name, ...) \ | |
107 | const VarlinkSymbol vl_method_ ## _name = { \ | |
108 | .name = #_name, \ | |
109 | .symbol_type = VARLINK_METHOD, \ | |
110 | .fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \ | |
111 | } | |
112 | ||
113 | #define VARLINK_DEFINE_ERROR(_name, ...) \ | |
114 | const VarlinkSymbol vl_error_ ## _name = { \ | |
115 | .name = #_name, \ | |
116 | .symbol_type = VARLINK_ERROR, \ | |
117 | .fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \ | |
118 | } | |
119 | ||
120 | #define VARLINK_DEFINE_STRUCT_TYPE(_name, ...) \ | |
121 | const VarlinkSymbol vl_type_ ## _name = { \ | |
122 | .name = #_name, \ | |
123 | .symbol_type = VARLINK_STRUCT_TYPE, \ | |
124 | .fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \ | |
125 | } | |
126 | ||
127 | #define VARLINK_DEFINE_ENUM_TYPE(_name, ...) \ | |
128 | const VarlinkSymbol vl_type_ ## _name = { \ | |
129 | .name = #_name, \ | |
130 | .symbol_type = VARLINK_ENUM_TYPE, \ | |
131 | .fields = { __VA_ARGS__ __VA_OPT__(,) {}}, \ | |
132 | } | |
133 | ||
134 | #define VARLINK_DEFINE_INTERFACE(_name, _full_name, ...) \ | |
135 | const VarlinkInterface vl_interface_ ## _name = { \ | |
136 | .name = (_full_name), \ | |
137 | .symbols = { __VA_ARGS__ __VA_OPT__(,) NULL}, \ | |
138 | } | |
139 | ||
140 | int varlink_idl_dump(FILE *f, int use_colors, const VarlinkInterface *interface); | |
141 | int varlink_idl_format(const VarlinkInterface *interface, char **ret); | |
142 | ||
143 | int varlink_idl_parse(const char *text, unsigned *ret_line, unsigned *ret_column, VarlinkInterface **ret); | |
144 | VarlinkInterface* varlink_interface_free(VarlinkInterface *interface); | |
145 | DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkInterface*, varlink_interface_free); | |
146 | ||
147 | bool varlink_idl_field_name_is_valid(const char *name); | |
148 | bool varlink_idl_symbol_name_is_valid(const char *name); | |
149 | bool varlink_idl_interface_name_is_valid(const char *name); | |
150 | ||
a972870e | 151 | int varlink_idl_consistent(const VarlinkInterface *interface, int level); |
e50b2a93 LP |
152 | |
153 | const VarlinkSymbol* varlink_idl_find_symbol(const VarlinkInterface *interface, VarlinkSymbolType type, const char *name); | |
154 | const VarlinkField* varlink_idl_find_field(const VarlinkSymbol *symbol, const char *name); | |
155 | ||
156 | int varlink_idl_validate_method_call(const VarlinkSymbol *method, JsonVariant *v, const char **bad_field); | |
157 | int varlink_idl_validate_method_reply(const VarlinkSymbol *method, JsonVariant *v, const char **bad_field); | |
158 | int varlink_idl_validate_error(const VarlinkSymbol *error, JsonVariant *v, const char **bad_field); |