blob: 43cb48d4f7d012d146920f941af2195a71ec1fe8 [file] [log] [blame]
Radek Krejcid6b76452019-09-03 17:03:03 +02001/**
2 * @file plugins_exts_nacm.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief libyang extension plugin - Metadata (RFC 7952)
5 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#include "common.h"
15
16#include <stdlib.h>
17
18#include "plugins_exts.h"
Radek Krejcid6b76452019-09-03 17:03:03 +020019#include "plugins_exts_metadata.h"
Michal Vasko1a7a7bd2020-10-16 14:39:15 +020020#include "schema_compile.h"
Michal Vasko69730152020-10-09 16:30:07 +020021#include "tree_schema.h"
Radek Krejcid6b76452019-09-03 17:03:03 +020022
23/**
24 * @brief Storage for ID used to check plugin API version compatibility.
25 * Ignored here in the internal plugin.
26LYEXT_VERSION_CHECK
27 */
28
Radek Krejci1b2eef82021-02-17 11:17:27 +010029/**
30 * @brief Representation of the compiled metadata substatements - simplify storage for the items available via
31 * ::lysc_ext_substmt.
32 */
33struct lyext_metadata {
34 struct lysc_type *type; /**< type of the metadata (mandatory) */
35 const char *units; /**< units of the leaf's type */
36 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
37 const char *dsc; /**< description */
38 const char *ref; /**< reference */
39 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
40};
Radek Krejci38d85362019-09-05 16:26:38 +020041
Radek Krejcid6b76452019-09-03 17:03:03 +020042/**
43 * @brief Compile annotation extension instances.
44 *
45 * Implementation of lyext_clb_compile callback set as lyext_plugin::compile.
46 */
47LY_ERR
48annotation_compile(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext)
49{
50 struct lyext_metadata *annotation;
51 struct lysc_module *mod_c;
Michal Vaskofd69e1d2020-07-03 11:57:17 +020052 LY_ARRAY_COUNT_TYPE u;
Radek Krejcid6b76452019-09-03 17:03:03 +020053
54 /* annotations can appear only at the top level of a YANG module or submodule */
Radek Krejciab430862021-03-02 20:13:40 +010055 if ((c_ext->parent_stmt != LY_STMT_MODULE) && (c_ext->parent_stmt != LY_STMT_SUBMODULE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020056 lyext_log(c_ext, LY_LLERR, LY_EVALID, cctx->path, "Extension %s is allowed only at the top level of a YANG module or submodule, but it is placed in \"%s\" statement.",
Radek Krejciab430862021-03-02 20:13:40 +010057 p_ext->name, ly_stmt2str(c_ext->parent_stmt));
Radek Krejcid6b76452019-09-03 17:03:03 +020058 return LY_EVALID;
59 }
Radek Krejci335332a2019-09-05 13:03:35 +020060 /* check mandatory argument */
61 if (!c_ext->argument) {
62 lyext_log(c_ext, LY_LLERR, LY_EVALID, cctx->path, "Extension %s is instantiated without mandatory argument representing metadata name.",
Michal Vasko69730152020-10-09 16:30:07 +020063 p_ext->name);
Radek Krejci335332a2019-09-05 13:03:35 +020064 return LY_EVALID;
65 }
Radek Krejcid6b76452019-09-03 17:03:03 +020066
67 mod_c = (struct lysc_module *)c_ext->parent;
68
69 /* check for duplication */
70 LY_ARRAY_FOR(mod_c->exts, u) {
Michal Vasko69730152020-10-09 16:30:07 +020071 if ((&mod_c->exts[u] != c_ext) && (mod_c->exts[u].def == c_ext->def) && !strcmp(mod_c->exts[u].argument, c_ext->argument)) {
Radek Krejci335332a2019-09-05 13:03:35 +020072 /* duplication of the same annotation extension in a single module */
Radek Krejcid6b76452019-09-03 17:03:03 +020073 lyext_log(c_ext, LY_LLERR, LY_EVALID, cctx->path, "Extension %s is instantiated multiple times.", p_ext->name);
74 return LY_EVALID;
75 }
76 }
77
78 /* compile annotation substatements */
Radek Krejci1b2eef82021-02-17 11:17:27 +010079 LY_ARRAY_CREATE_RET(cctx->ctx, c_ext->substmts, 6, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +020080 c_ext->data = annotation = calloc(1, sizeof *annotation);
Radek Krejci1b2eef82021-02-17 11:17:27 +010081 if (!annotation) {
82 LOGMEM(cctx->ctx);
83 LY_ARRAY_FREE(c_ext->substmts);
84 c_ext->substmts = NULL;
85 return LY_EMEM;
86 }
Radek Krejcid6b76452019-09-03 17:03:03 +020087
Radek Krejci1b2eef82021-02-17 11:17:27 +010088 LY_ARRAY_INCREMENT(c_ext->substmts);
89 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].stmt = LY_STMT_IF_FEATURE;
90 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].cardinality = LY_STMT_CARD_ANY;
91 c_ext->substmts[ANNOTATION_SUBSTMT_IFF].storage = &annotation->iffeatures;
92
93 LY_ARRAY_INCREMENT(c_ext->substmts);
94 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].stmt = LY_STMT_UNITS;
95 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].cardinality = LY_STMT_CARD_OPT;
96 c_ext->substmts[ANNOTATION_SUBSTMT_UNITS].storage = &annotation->units;
97
98 LY_ARRAY_INCREMENT(c_ext->substmts);
99 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].stmt = LY_STMT_STATUS;
100 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].cardinality = LY_STMT_CARD_OPT;
101 c_ext->substmts[ANNOTATION_SUBSTMT_STATUS].storage = &annotation->flags;
102
103 LY_ARRAY_INCREMENT(c_ext->substmts);
104 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].stmt = LY_STMT_TYPE;
105 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].cardinality = LY_STMT_CARD_MAND;
106 c_ext->substmts[ANNOTATION_SUBSTMT_TYPE].storage = &annotation->type;
107
108 LY_ARRAY_INCREMENT(c_ext->substmts);
109 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].stmt = LY_STMT_DESCRIPTION;
110 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].cardinality = LY_STMT_CARD_OPT;
111 c_ext->substmts[ANNOTATION_SUBSTMT_DSC].storage = &annotation->dsc;
112
113 LY_ARRAY_INCREMENT(c_ext->substmts);
114 c_ext->substmts[ANNOTATION_SUBSTMT_REF].stmt = LY_STMT_REFERENCE;
115 c_ext->substmts[ANNOTATION_SUBSTMT_REF].cardinality = LY_STMT_CARD_OPT;
116 c_ext->substmts[ANNOTATION_SUBSTMT_REF].storage = &annotation->ref;
117
Radek Krejci6b88a462021-02-17 12:39:34 +0100118 LY_CHECK_RET(lys_compile_extension_instance(cctx, p_ext, c_ext));
Radek Krejcid6b76452019-09-03 17:03:03 +0200119
120 return LY_SUCCESS;
121}
122
Radek Krejci38d85362019-09-05 16:26:38 +0200123/**
Radek Krejciadcf63d2021-02-09 10:21:18 +0100124 * @brief INFO printer
125 *
126 * Implementation of lyext_clb_schema_printer set as ::lyext_plugin::sprinter
127 */
128LY_ERR
129annotation_schema_printer(struct lys_ypr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag)
130{
131 lysc_print_extension_instance(ctx, ext, flag);
132
133 return LY_SUCCESS;
134}
135
136/**
Radek Krejci38d85362019-09-05 16:26:38 +0200137 * @brief Free annotation extension instances' data.
138 *
Radek Krejciadcf63d2021-02-09 10:21:18 +0100139 * Implementation of lyext_clb_free callback set as ::lyext_plugin::free.
Radek Krejci38d85362019-09-05 16:26:38 +0200140 */
141void
142annotation_free(struct ly_ctx *ctx, struct lysc_ext_instance *ext)
143{
Radek Krejci1b2eef82021-02-17 11:17:27 +0100144 if (!ext->substmts) {
Radek Krejciad5963b2019-09-06 16:03:05 +0200145 return;
146 }
147
Radek Krejci1b2eef82021-02-17 11:17:27 +0100148 lysc_extension_instance_substatements_free(ctx, ext->substmts);
Radek Krejci0f969882020-08-21 16:56:47 +0200149 free(ext->data);
Radek Krejci38d85362019-09-05 16:26:38 +0200150}
Radek Krejcid6b76452019-09-03 17:03:03 +0200151
152/**
153 * @brief Plugin for the Metadata's annotation extension
154 */
155struct lyext_plugin metadata_plugin = {
156 .id = "libyang 2 - metadata, version 1",
157 .compile = &annotation_compile,
158 .validate = NULL,
Radek Krejciadcf63d2021-02-09 10:21:18 +0100159 .sprinter = &annotation_schema_printer,
Radek Krejci38d85362019-09-05 16:26:38 +0200160 .free = annotation_free
Radek Krejcid6b76452019-09-03 17:03:03 +0200161};