xref: /qemu/qapi/qapi-forward-visitor.c (revision 4ea4bec6)
118fa3ebcSPaolo Bonzini /*
218fa3ebcSPaolo Bonzini  * Forward Visitor
318fa3ebcSPaolo Bonzini  *
418fa3ebcSPaolo Bonzini  * Copyright (C) 2021 Red Hat, Inc.
518fa3ebcSPaolo Bonzini  *
618fa3ebcSPaolo Bonzini  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
718fa3ebcSPaolo Bonzini  * See the COPYING.LIB file in the top-level directory.
818fa3ebcSPaolo Bonzini  *
918fa3ebcSPaolo Bonzini  */
1018fa3ebcSPaolo Bonzini 
1118fa3ebcSPaolo Bonzini #include "qemu/osdep.h"
1218fa3ebcSPaolo Bonzini #include "qapi/compat-policy.h"
1318fa3ebcSPaolo Bonzini #include "qapi/error.h"
1418fa3ebcSPaolo Bonzini #include "qapi/forward-visitor.h"
1518fa3ebcSPaolo Bonzini #include "qapi/visitor-impl.h"
1618fa3ebcSPaolo Bonzini #include "qemu/queue.h"
1718fa3ebcSPaolo Bonzini #include "qapi/qmp/qjson.h"
1818fa3ebcSPaolo Bonzini #include "qapi/qmp/qbool.h"
1918fa3ebcSPaolo Bonzini #include "qapi/qmp/qdict.h"
2018fa3ebcSPaolo Bonzini #include "qapi/qmp/qerror.h"
2118fa3ebcSPaolo Bonzini #include "qapi/qmp/qlist.h"
2218fa3ebcSPaolo Bonzini #include "qapi/qmp/qnull.h"
2318fa3ebcSPaolo Bonzini #include "qapi/qmp/qnum.h"
2418fa3ebcSPaolo Bonzini #include "qapi/qmp/qstring.h"
2518fa3ebcSPaolo Bonzini #include "qemu/cutils.h"
2618fa3ebcSPaolo Bonzini 
2718fa3ebcSPaolo Bonzini struct ForwardFieldVisitor {
2818fa3ebcSPaolo Bonzini     Visitor visitor;
2918fa3ebcSPaolo Bonzini 
3018fa3ebcSPaolo Bonzini     Visitor *target;
3118fa3ebcSPaolo Bonzini     char *from;
3218fa3ebcSPaolo Bonzini     char *to;
3318fa3ebcSPaolo Bonzini 
3418fa3ebcSPaolo Bonzini     int depth;
3518fa3ebcSPaolo Bonzini };
3618fa3ebcSPaolo Bonzini 
to_ffv(Visitor * v)3718fa3ebcSPaolo Bonzini static ForwardFieldVisitor *to_ffv(Visitor *v)
3818fa3ebcSPaolo Bonzini {
3918fa3ebcSPaolo Bonzini     return container_of(v, ForwardFieldVisitor, visitor);
4018fa3ebcSPaolo Bonzini }
4118fa3ebcSPaolo Bonzini 
forward_field_translate_name(ForwardFieldVisitor * v,const char ** name,Error ** errp)4218fa3ebcSPaolo Bonzini static bool forward_field_translate_name(ForwardFieldVisitor *v, const char **name,
4318fa3ebcSPaolo Bonzini                                          Error **errp)
4418fa3ebcSPaolo Bonzini {
4518fa3ebcSPaolo Bonzini     if (v->depth) {
4618fa3ebcSPaolo Bonzini         return true;
4718fa3ebcSPaolo Bonzini     }
4818fa3ebcSPaolo Bonzini     if (g_str_equal(*name, v->from)) {
4918fa3ebcSPaolo Bonzini         *name = v->to;
5018fa3ebcSPaolo Bonzini         return true;
5118fa3ebcSPaolo Bonzini     }
5218fa3ebcSPaolo Bonzini     error_setg(errp, QERR_MISSING_PARAMETER, *name);
5318fa3ebcSPaolo Bonzini     return false;
5418fa3ebcSPaolo Bonzini }
5518fa3ebcSPaolo Bonzini 
forward_field_check_struct(Visitor * v,Error ** errp)5618fa3ebcSPaolo Bonzini static bool forward_field_check_struct(Visitor *v, Error **errp)
5718fa3ebcSPaolo Bonzini {
5818fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
5918fa3ebcSPaolo Bonzini 
6018fa3ebcSPaolo Bonzini     return visit_check_struct(ffv->target, errp);
6118fa3ebcSPaolo Bonzini }
6218fa3ebcSPaolo Bonzini 
forward_field_start_struct(Visitor * v,const char * name,void ** obj,size_t size,Error ** errp)6318fa3ebcSPaolo Bonzini static bool forward_field_start_struct(Visitor *v, const char *name, void **obj,
6418fa3ebcSPaolo Bonzini                                        size_t size, Error **errp)
6518fa3ebcSPaolo Bonzini {
6618fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
6718fa3ebcSPaolo Bonzini 
6818fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
6918fa3ebcSPaolo Bonzini         return false;
7018fa3ebcSPaolo Bonzini     }
7118fa3ebcSPaolo Bonzini     if (!visit_start_struct(ffv->target, name, obj, size, errp)) {
7218fa3ebcSPaolo Bonzini         return false;
7318fa3ebcSPaolo Bonzini     }
7418fa3ebcSPaolo Bonzini     ffv->depth++;
7518fa3ebcSPaolo Bonzini     return true;
7618fa3ebcSPaolo Bonzini }
7718fa3ebcSPaolo Bonzini 
forward_field_end_struct(Visitor * v,void ** obj)7818fa3ebcSPaolo Bonzini static void forward_field_end_struct(Visitor *v, void **obj)
7918fa3ebcSPaolo Bonzini {
8018fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
8118fa3ebcSPaolo Bonzini 
8218fa3ebcSPaolo Bonzini     assert(ffv->depth);
8318fa3ebcSPaolo Bonzini     ffv->depth--;
8418fa3ebcSPaolo Bonzini     visit_end_struct(ffv->target, obj);
8518fa3ebcSPaolo Bonzini }
8618fa3ebcSPaolo Bonzini 
forward_field_start_list(Visitor * v,const char * name,GenericList ** list,size_t size,Error ** errp)8718fa3ebcSPaolo Bonzini static bool forward_field_start_list(Visitor *v, const char *name,
8818fa3ebcSPaolo Bonzini                                      GenericList **list, size_t size,
8918fa3ebcSPaolo Bonzini                                      Error **errp)
9018fa3ebcSPaolo Bonzini {
9118fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
9218fa3ebcSPaolo Bonzini 
9318fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
9418fa3ebcSPaolo Bonzini         return false;
9518fa3ebcSPaolo Bonzini     }
9618fa3ebcSPaolo Bonzini     ffv->depth++;
9718fa3ebcSPaolo Bonzini     return visit_start_list(ffv->target, name, list, size, errp);
9818fa3ebcSPaolo Bonzini }
9918fa3ebcSPaolo Bonzini 
forward_field_next_list(Visitor * v,GenericList * tail,size_t size)10018fa3ebcSPaolo Bonzini static GenericList *forward_field_next_list(Visitor *v, GenericList *tail,
10118fa3ebcSPaolo Bonzini                                             size_t size)
10218fa3ebcSPaolo Bonzini {
10318fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
10418fa3ebcSPaolo Bonzini 
10518fa3ebcSPaolo Bonzini     assert(ffv->depth);
10618fa3ebcSPaolo Bonzini     return visit_next_list(ffv->target, tail, size);
10718fa3ebcSPaolo Bonzini }
10818fa3ebcSPaolo Bonzini 
forward_field_check_list(Visitor * v,Error ** errp)10918fa3ebcSPaolo Bonzini static bool forward_field_check_list(Visitor *v, Error **errp)
11018fa3ebcSPaolo Bonzini {
11118fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
11218fa3ebcSPaolo Bonzini 
11318fa3ebcSPaolo Bonzini     assert(ffv->depth);
11418fa3ebcSPaolo Bonzini     return visit_check_list(ffv->target, errp);
11518fa3ebcSPaolo Bonzini }
11618fa3ebcSPaolo Bonzini 
forward_field_end_list(Visitor * v,void ** obj)11718fa3ebcSPaolo Bonzini static void forward_field_end_list(Visitor *v, void **obj)
11818fa3ebcSPaolo Bonzini {
11918fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
12018fa3ebcSPaolo Bonzini 
12118fa3ebcSPaolo Bonzini     assert(ffv->depth);
12218fa3ebcSPaolo Bonzini     ffv->depth--;
12318fa3ebcSPaolo Bonzini     visit_end_list(ffv->target, obj);
12418fa3ebcSPaolo Bonzini }
12518fa3ebcSPaolo Bonzini 
forward_field_start_alternate(Visitor * v,const char * name,GenericAlternate ** obj,size_t size,Error ** errp)12618fa3ebcSPaolo Bonzini static bool forward_field_start_alternate(Visitor *v, const char *name,
12718fa3ebcSPaolo Bonzini                                           GenericAlternate **obj, size_t size,
12818fa3ebcSPaolo Bonzini                                           Error **errp)
12918fa3ebcSPaolo Bonzini {
13018fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
13118fa3ebcSPaolo Bonzini 
13218fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
13318fa3ebcSPaolo Bonzini         return false;
13418fa3ebcSPaolo Bonzini     }
13518fa3ebcSPaolo Bonzini     /*
13618fa3ebcSPaolo Bonzini      * The name passed to start_alternate is used also in the visit_type_* calls
13718fa3ebcSPaolo Bonzini      * that retrieve the alternate's content; so, do not increase depth here.
13818fa3ebcSPaolo Bonzini      */
13918fa3ebcSPaolo Bonzini     return visit_start_alternate(ffv->target, name, obj, size, errp);
14018fa3ebcSPaolo Bonzini }
14118fa3ebcSPaolo Bonzini 
forward_field_end_alternate(Visitor * v,void ** obj)14218fa3ebcSPaolo Bonzini static void forward_field_end_alternate(Visitor *v, void **obj)
14318fa3ebcSPaolo Bonzini {
14418fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
14518fa3ebcSPaolo Bonzini 
14618fa3ebcSPaolo Bonzini     visit_end_alternate(ffv->target, obj);
14718fa3ebcSPaolo Bonzini }
14818fa3ebcSPaolo Bonzini 
forward_field_type_int64(Visitor * v,const char * name,int64_t * obj,Error ** errp)14918fa3ebcSPaolo Bonzini static bool forward_field_type_int64(Visitor *v, const char *name, int64_t *obj,
15018fa3ebcSPaolo Bonzini                                      Error **errp)
15118fa3ebcSPaolo Bonzini {
15218fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
15318fa3ebcSPaolo Bonzini 
15418fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
15518fa3ebcSPaolo Bonzini         return false;
15618fa3ebcSPaolo Bonzini     }
15718fa3ebcSPaolo Bonzini     return visit_type_int64(ffv->target, name, obj, errp);
15818fa3ebcSPaolo Bonzini }
15918fa3ebcSPaolo Bonzini 
forward_field_type_uint64(Visitor * v,const char * name,uint64_t * obj,Error ** errp)16018fa3ebcSPaolo Bonzini static bool forward_field_type_uint64(Visitor *v, const char *name,
16118fa3ebcSPaolo Bonzini                                       uint64_t *obj, Error **errp)
16218fa3ebcSPaolo Bonzini {
16318fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
16418fa3ebcSPaolo Bonzini 
16518fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
16618fa3ebcSPaolo Bonzini         return false;
16718fa3ebcSPaolo Bonzini     }
16818fa3ebcSPaolo Bonzini     return visit_type_uint64(ffv->target, name, obj, errp);
16918fa3ebcSPaolo Bonzini }
17018fa3ebcSPaolo Bonzini 
forward_field_type_bool(Visitor * v,const char * name,bool * obj,Error ** errp)17118fa3ebcSPaolo Bonzini static bool forward_field_type_bool(Visitor *v, const char *name, bool *obj,
17218fa3ebcSPaolo Bonzini                                     Error **errp)
17318fa3ebcSPaolo Bonzini {
17418fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
17518fa3ebcSPaolo Bonzini 
17618fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
17718fa3ebcSPaolo Bonzini         return false;
17818fa3ebcSPaolo Bonzini     }
17918fa3ebcSPaolo Bonzini     return visit_type_bool(ffv->target, name, obj, errp);
18018fa3ebcSPaolo Bonzini }
18118fa3ebcSPaolo Bonzini 
forward_field_type_str(Visitor * v,const char * name,char ** obj,Error ** errp)18218fa3ebcSPaolo Bonzini static bool forward_field_type_str(Visitor *v, const char *name, char **obj,
18318fa3ebcSPaolo Bonzini                                    Error **errp)
18418fa3ebcSPaolo Bonzini {
18518fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
18618fa3ebcSPaolo Bonzini 
18718fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
18818fa3ebcSPaolo Bonzini         return false;
18918fa3ebcSPaolo Bonzini     }
19018fa3ebcSPaolo Bonzini     return visit_type_str(ffv->target, name, obj, errp);
19118fa3ebcSPaolo Bonzini }
19218fa3ebcSPaolo Bonzini 
forward_field_type_size(Visitor * v,const char * name,uint64_t * obj,Error ** errp)19318fa3ebcSPaolo Bonzini static bool forward_field_type_size(Visitor *v, const char *name, uint64_t *obj,
19418fa3ebcSPaolo Bonzini                                     Error **errp)
19518fa3ebcSPaolo Bonzini {
19618fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
19718fa3ebcSPaolo Bonzini 
19818fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
19918fa3ebcSPaolo Bonzini         return false;
20018fa3ebcSPaolo Bonzini     }
20118fa3ebcSPaolo Bonzini     return visit_type_size(ffv->target, name, obj, errp);
20218fa3ebcSPaolo Bonzini }
20318fa3ebcSPaolo Bonzini 
forward_field_type_number(Visitor * v,const char * name,double * obj,Error ** errp)20418fa3ebcSPaolo Bonzini static bool forward_field_type_number(Visitor *v, const char *name, double *obj,
20518fa3ebcSPaolo Bonzini                                       Error **errp)
20618fa3ebcSPaolo Bonzini {
20718fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
20818fa3ebcSPaolo Bonzini 
20918fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
21018fa3ebcSPaolo Bonzini         return false;
21118fa3ebcSPaolo Bonzini     }
21218fa3ebcSPaolo Bonzini     return visit_type_number(ffv->target, name, obj, errp);
21318fa3ebcSPaolo Bonzini }
21418fa3ebcSPaolo Bonzini 
forward_field_type_any(Visitor * v,const char * name,QObject ** obj,Error ** errp)21518fa3ebcSPaolo Bonzini static bool forward_field_type_any(Visitor *v, const char *name, QObject **obj,
21618fa3ebcSPaolo Bonzini                                    Error **errp)
21718fa3ebcSPaolo Bonzini {
21818fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
21918fa3ebcSPaolo Bonzini 
22018fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
22118fa3ebcSPaolo Bonzini         return false;
22218fa3ebcSPaolo Bonzini     }
22318fa3ebcSPaolo Bonzini     return visit_type_any(ffv->target, name, obj, errp);
22418fa3ebcSPaolo Bonzini }
22518fa3ebcSPaolo Bonzini 
forward_field_type_null(Visitor * v,const char * name,QNull ** obj,Error ** errp)22618fa3ebcSPaolo Bonzini static bool forward_field_type_null(Visitor *v, const char *name,
22718fa3ebcSPaolo Bonzini                                     QNull **obj, Error **errp)
22818fa3ebcSPaolo Bonzini {
22918fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
23018fa3ebcSPaolo Bonzini 
23118fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
23218fa3ebcSPaolo Bonzini         return false;
23318fa3ebcSPaolo Bonzini     }
23418fa3ebcSPaolo Bonzini     return visit_type_null(ffv->target, name, obj, errp);
23518fa3ebcSPaolo Bonzini }
23618fa3ebcSPaolo Bonzini 
forward_field_optional(Visitor * v,const char * name,bool * present)23718fa3ebcSPaolo Bonzini static void forward_field_optional(Visitor *v, const char *name, bool *present)
23818fa3ebcSPaolo Bonzini {
23918fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
24018fa3ebcSPaolo Bonzini 
24118fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, NULL)) {
24218fa3ebcSPaolo Bonzini         *present = false;
24318fa3ebcSPaolo Bonzini         return;
24418fa3ebcSPaolo Bonzini     }
24518fa3ebcSPaolo Bonzini     visit_optional(ffv->target, name, present);
24618fa3ebcSPaolo Bonzini }
24718fa3ebcSPaolo Bonzini 
forward_field_policy_reject(Visitor * v,const char * name,unsigned special_features,Error ** errp)248*a1307285SMarkus Armbruster static bool forward_field_policy_reject(Visitor *v, const char *name,
249*a1307285SMarkus Armbruster                                         unsigned special_features,
25018fa3ebcSPaolo Bonzini                                         Error **errp)
25118fa3ebcSPaolo Bonzini {
25218fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
25318fa3ebcSPaolo Bonzini 
25418fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, errp)) {
255*a1307285SMarkus Armbruster         return true;
25618fa3ebcSPaolo Bonzini     }
257*a1307285SMarkus Armbruster     return visit_policy_reject(ffv->target, name, special_features, errp);
25818fa3ebcSPaolo Bonzini }
25918fa3ebcSPaolo Bonzini 
forward_field_policy_skip(Visitor * v,const char * name,unsigned special_features)260*a1307285SMarkus Armbruster static bool forward_field_policy_skip(Visitor *v, const char *name,
261*a1307285SMarkus Armbruster                                       unsigned special_features)
26218fa3ebcSPaolo Bonzini {
26318fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
26418fa3ebcSPaolo Bonzini 
26518fa3ebcSPaolo Bonzini     if (!forward_field_translate_name(ffv, &name, NULL)) {
266*a1307285SMarkus Armbruster         return true;
26718fa3ebcSPaolo Bonzini     }
268*a1307285SMarkus Armbruster     return visit_policy_skip(ffv->target, name, special_features);
26918fa3ebcSPaolo Bonzini }
27018fa3ebcSPaolo Bonzini 
forward_field_complete(Visitor * v,void * opaque)27118fa3ebcSPaolo Bonzini static void forward_field_complete(Visitor *v, void *opaque)
27218fa3ebcSPaolo Bonzini {
27318fa3ebcSPaolo Bonzini     /*
27418fa3ebcSPaolo Bonzini      * Do nothing, the complete method will be called in due time
27518fa3ebcSPaolo Bonzini      * on the target visitor.
27618fa3ebcSPaolo Bonzini      */
27718fa3ebcSPaolo Bonzini }
27818fa3ebcSPaolo Bonzini 
forward_field_free(Visitor * v)27918fa3ebcSPaolo Bonzini static void forward_field_free(Visitor *v)
28018fa3ebcSPaolo Bonzini {
28118fa3ebcSPaolo Bonzini     ForwardFieldVisitor *ffv = to_ffv(v);
28218fa3ebcSPaolo Bonzini 
28318fa3ebcSPaolo Bonzini     g_free(ffv->from);
28418fa3ebcSPaolo Bonzini     g_free(ffv->to);
28518fa3ebcSPaolo Bonzini     g_free(ffv);
28618fa3ebcSPaolo Bonzini }
28718fa3ebcSPaolo Bonzini 
visitor_forward_field(Visitor * target,const char * from,const char * to)28818fa3ebcSPaolo Bonzini Visitor *visitor_forward_field(Visitor *target, const char *from, const char *to)
28918fa3ebcSPaolo Bonzini {
29018fa3ebcSPaolo Bonzini     ForwardFieldVisitor *v = g_new0(ForwardFieldVisitor, 1);
29118fa3ebcSPaolo Bonzini 
29218fa3ebcSPaolo Bonzini     /*
29318fa3ebcSPaolo Bonzini      * Clone and dealloc visitors don't use a name for the toplevel
29418fa3ebcSPaolo Bonzini      * visit, so they make no sense here.
29518fa3ebcSPaolo Bonzini      */
29618fa3ebcSPaolo Bonzini     assert(target->type == VISITOR_OUTPUT || target->type == VISITOR_INPUT);
29718fa3ebcSPaolo Bonzini 
29818fa3ebcSPaolo Bonzini     v->visitor.type = target->type;
29918fa3ebcSPaolo Bonzini     v->visitor.start_struct = forward_field_start_struct;
30018fa3ebcSPaolo Bonzini     v->visitor.check_struct = forward_field_check_struct;
30118fa3ebcSPaolo Bonzini     v->visitor.end_struct = forward_field_end_struct;
30218fa3ebcSPaolo Bonzini     v->visitor.start_list = forward_field_start_list;
30318fa3ebcSPaolo Bonzini     v->visitor.next_list = forward_field_next_list;
30418fa3ebcSPaolo Bonzini     v->visitor.check_list = forward_field_check_list;
30518fa3ebcSPaolo Bonzini     v->visitor.end_list = forward_field_end_list;
30618fa3ebcSPaolo Bonzini     v->visitor.start_alternate = forward_field_start_alternate;
30718fa3ebcSPaolo Bonzini     v->visitor.end_alternate = forward_field_end_alternate;
30818fa3ebcSPaolo Bonzini     v->visitor.type_int64 = forward_field_type_int64;
30918fa3ebcSPaolo Bonzini     v->visitor.type_uint64 = forward_field_type_uint64;
31018fa3ebcSPaolo Bonzini     v->visitor.type_size = forward_field_type_size;
31118fa3ebcSPaolo Bonzini     v->visitor.type_bool = forward_field_type_bool;
31218fa3ebcSPaolo Bonzini     v->visitor.type_str = forward_field_type_str;
31318fa3ebcSPaolo Bonzini     v->visitor.type_number = forward_field_type_number;
31418fa3ebcSPaolo Bonzini     v->visitor.type_any = forward_field_type_any;
31518fa3ebcSPaolo Bonzini     v->visitor.type_null = forward_field_type_null;
31618fa3ebcSPaolo Bonzini     v->visitor.optional = forward_field_optional;
317*a1307285SMarkus Armbruster     v->visitor.policy_reject = forward_field_policy_reject;
318*a1307285SMarkus Armbruster     v->visitor.policy_skip = forward_field_policy_skip;
31918fa3ebcSPaolo Bonzini     v->visitor.complete = forward_field_complete;
32018fa3ebcSPaolo Bonzini     v->visitor.free = forward_field_free;
32118fa3ebcSPaolo Bonzini 
32218fa3ebcSPaolo Bonzini     v->target = target;
32318fa3ebcSPaolo Bonzini     v->from = g_strdup(from);
32418fa3ebcSPaolo Bonzini     v->to = g_strdup(to);
32518fa3ebcSPaolo Bonzini 
32618fa3ebcSPaolo Bonzini     return &v->visitor;
32718fa3ebcSPaolo Bonzini }
328