qapi: Implement deprecated-input={reject,crash} for enum values

This copies the code implementing the policy from qapi/qmp-dispatch.c
to qapi/qobject-input-visitor.c.  Tolerable, but if we acquire more
copies, we should look into factoring them out.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Tested-by: Peter Krempa <pkrempa@redhat.com>
Acked-by: Peter Krempa <pkrempa@redhat.com>
Message-Id: <20211025042405.3762351-5-armbru@redhat.com>
This commit is contained in:
Markus Armbruster 2021-10-25 06:24:04 +02:00
parent ed29bb28f8
commit aa2370444b
4 changed files with 38 additions and 6 deletions

View File

@ -11,9 +11,13 @@
#ifndef QAPI_UTIL_H
#define QAPI_UTIL_H
/* QEnumLookup flags */
#define QAPI_ENUM_DEPRECATED 1
typedef struct QEnumLookup {
const char *const *array;
int size;
const unsigned char *const flags;
const int size;
} QEnumLookup;
const char *qapi_enum_lookup(const QEnumLookup *lookup, int val);

View File

@ -42,7 +42,8 @@
# with feature 'deprecated'. We may want to extend it to cover
# semantic aspects, CLI, and experimental features.
#
# Limitation: not implemented for deprecated enumeration values.
# Limitation: deprecated-output policy @hide is not implemented for
# enumeration values. They behave the same as with policy @accept.
#
# @deprecated-input: how to handle deprecated input (default 'accept')
# @deprecated-output: how to handle deprecated output (default 'accept')

View File

@ -393,7 +393,7 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
const QEnumLookup *lookup, Error **errp)
{
int64_t value;
char *enum_str;
g_autofree char *enum_str = NULL;
if (!visit_type_str(v, name, &enum_str, errp)) {
return false;
@ -403,11 +403,23 @@ static bool input_type_enum(Visitor *v, const char *name, int *obj,
if (value < 0) {
error_setg(errp, "Parameter '%s' does not accept value '%s'",
name ? name : "null", enum_str);
g_free(enum_str);
return false;
}
g_free(enum_str);
if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) {
switch (v->compat_policy.deprecated_input) {
case COMPAT_POLICY_INPUT_ACCEPT:
break;
case COMPAT_POLICY_INPUT_REJECT:
error_setg(errp, "Deprecated value '%s' disabled by policy",
enum_str);
return false;
case COMPAT_POLICY_INPUT_CRASH:
default:
abort();
}
}
*obj = value;
return true;
}

View File

@ -38,6 +38,8 @@ objects_seen = set()
def gen_enum_lookup(name: str,
members: List[QAPISchemaEnumMember],
prefix: Optional[str] = None) -> str:
max_index = c_enum_const(name, '_MAX', prefix)
flags = ''
ret = mcgen('''
const QEnumLookup %(c_name)s_lookup = {
@ -52,13 +54,26 @@ const QEnumLookup %(c_name)s_lookup = {
''',
index=index, name=memb.name)
ret += memb.ifcond.gen_endif()
if 'deprecated' in (f.name for f in memb.features):
flags += mcgen('''
[%(index)s] = QAPI_ENUM_DEPRECATED,
''',
index=index)
if flags:
ret += mcgen('''
},
.flags = (const unsigned char[%(max_index)s]) {
''',
max_index=max_index)
ret += flags
ret += mcgen('''
},
.size = %(max_index)s
};
''',
max_index=c_enum_const(name, '_MAX', prefix))
max_index=max_index)
return ret