blob: 8ff4d65b8125f88ee4047a361a430948caa8e52a [file] [log] [blame]
Václav Kubernátdaf40312020-06-19 11:34:55 +02001#include <boost/algorithm/string/predicate.hpp>
Jan Kundrátbd3169c2020-02-03 19:31:34 +01002#include <cmath>
Václav Kubernátcfdb9222021-07-07 22:36:24 +02003#include <libyang-cpp/Context.hpp>
Václav Kubernát3c8fe022020-06-04 01:35:03 +02004#include "datastore_access.hpp"
5#include "libyang_utils.hpp"
6#include "utils.hpp"
Václav Kubernát02a71152020-01-21 14:52:51 +01007
Václav Kubernátcfdb9222021-07-07 22:36:24 +02008struct impl_leafValueFromNode {
9 leaf_data_ operator()(const libyang::Empty) const
10 {
11 return empty_{};
12 }
13
14 leaf_data_ operator()(const libyang::Binary& bin) const
15 {
16 return binary_{std::string{bin.base64}};
17 }
18
19 leaf_data_ operator()(const std::vector<libyang::Bit>& bits) const
20 {
21 bits_ res;
22 std::transform(bits.begin(), bits.end(), std::back_inserter(res.m_bits), [] (const libyang::Bit& bit) {
23 return bit.name;
24 });
25 return res;
26 }
27
28 leaf_data_ operator()(const libyang::Enum& enumVal) const
29 {
30 return enum_{enumVal.name};
31 }
32
33 leaf_data_ operator()(const libyang::IdentityRef& identRef) const
34 {
35 return identityRef_{identRef.module, identRef.name};
36 }
37
38 leaf_data_ operator()(const libyang::Decimal64& dec) const
39 {
40 return dec.number * std::pow(10, -dec.digits);
41 }
42
Jan Kundrátbb7aa852023-08-30 11:51:43 +020043 leaf_data_ operator()(const libyang::InstanceIdentifier& node) const
Václav Kubernátcfdb9222021-07-07 22:36:24 +020044 {
Jan Kundrátbb7aa852023-08-30 11:51:43 +020045 return instanceIdentifier_{node.path};
Václav Kubernátcfdb9222021-07-07 22:36:24 +020046 }
47
48 template <typename Type>
49 leaf_data_ operator()(const Type& val) const
50 {
51 return val;
52 }
53};
54
55leaf_data_ leafValueFromNode(libyang::DataNodeTerm node)
Václav Kubernát02a71152020-01-21 14:52:51 +010056{
Václav Kubernátcfdb9222021-07-07 22:36:24 +020057 return std::visit(impl_leafValueFromNode{},node.value());
Václav Kubernát02a71152020-01-21 14:52:51 +010058}
Václav Kubernát3c8fe022020-06-04 01:35:03 +020059
Václav Kubernátdaf40312020-06-19 11:34:55 +020060namespace {
Václav Kubernátcfdb9222021-07-07 22:36:24 +020061template <typename CollectionType>
62void impl_lyNodesToTree(DatastoreAccess::Tree& res, CollectionType items, std::optional<std::string> ignoredXPathPrefix)
Václav Kubernát3c8fe022020-06-04 01:35:03 +020063{
Václav Kubernátb4e5b182020-11-16 19:55:09 +010064 auto stripXPathPrefix = [&ignoredXPathPrefix](auto path) {
Václav Kubernáta8789602020-07-20 15:18:19 +020065 return ignoredXPathPrefix && path.find(*ignoredXPathPrefix) != std::string::npos ? path.substr(ignoredXPathPrefix->size()) : path;
Václav Kubernát3c8fe022020-06-04 01:35:03 +020066 };
67
68 for (const auto& it : items) {
Václav Kubernátcfdb9222021-07-07 22:36:24 +020069 if (it.schema().nodeType() == libyang::NodeType::Container) {
70 if (it.schema().asContainer().isPresence()) {
Václav Kubernát3c8fe022020-06-04 01:35:03 +020071 // The fact that the container is included in the data tree
72 // means that it is present and I don't need to check any
73 // value.
Václav Kubernátcfdb9222021-07-07 22:36:24 +020074 res.emplace_back(stripXPathPrefix(std::string{it.path()}), special_{SpecialValue::PresenceContainer});
Václav Kubernát3c8fe022020-06-04 01:35:03 +020075 }
76 }
Václav Kubernátcfdb9222021-07-07 22:36:24 +020077 if (it.schema().nodeType() == libyang::NodeType::List) {
78 res.emplace_back(stripXPathPrefix(std::string{it.path()}), special_{SpecialValue::List});
Václav Kubernát3c8fe022020-06-04 01:35:03 +020079 }
Václav Kubernátcfdb9222021-07-07 22:36:24 +020080 if (it.schema().nodeType() == libyang::NodeType::Leaf || it.schema().nodeType() == libyang::NodeType::Leaflist) {
81 auto term = it.asTerm();
82 auto value = leafValueFromNode(term);
83 res.emplace_back(stripXPathPrefix(std::string{it.path()}), value);
Václav Kubernát3c8fe022020-06-04 01:35:03 +020084 }
85 }
86}
Václav Kubernátdaf40312020-06-19 11:34:55 +020087}
88
Václav Kubernátcfdb9222021-07-07 22:36:24 +020089template <typename CollectionType>
90void lyNodesToTree(DatastoreAccess::Tree& res, CollectionType items, std::optional<std::string> ignoredXPathPrefix)
Václav Kubernátdaf40312020-06-19 11:34:55 +020091{
Václav Kubernátcfdb9222021-07-07 22:36:24 +020092 for (auto it = items.begin(); it != items.end(); /* nothing */) {
93 if ((*it).schema().nodeType() == libyang::NodeType::Leaflist) {
94 auto leafListPath = stripLeafListValueFromPath(std::string{(*it).path()});
Václav Kubernátdaf40312020-06-19 11:34:55 +020095 res.emplace_back(leafListPath, special_{SpecialValue::LeafList});
Václav Kubernátcfdb9222021-07-07 22:36:24 +020096 while (it != items.end() && boost::starts_with(std::string{(*it).path()}, leafListPath)) {
97 impl_lyNodesToTree(res, it->childrenDfs(), ignoredXPathPrefix);
Václav Kubernátdaf40312020-06-19 11:34:55 +020098 it++;
99 }
100 } else {
Václav Kubernátcfdb9222021-07-07 22:36:24 +0200101 impl_lyNodesToTree(res, it->childrenDfs(), ignoredXPathPrefix);
102 it++;
Václav Kubernátdaf40312020-06-19 11:34:55 +0200103 }
104 }
105}
Václav Kubernátfbab2d42021-02-05 16:12:34 +0100106
Václav Kubernátcfdb9222021-07-07 22:36:24 +0200107using SiblingColl = libyang::Collection<libyang::DataNode, libyang::IterationType::Sibling>;
108using DfsColl = libyang::Collection<libyang::DataNode, libyang::IterationType::Dfs>;
109
110template
111void lyNodesToTree<SiblingColl>(DatastoreAccess::Tree& res, SiblingColl items, std::optional<std::string> ignoredXPathPrefix);
112template
113void lyNodesToTree<DfsColl>(DatastoreAccess::Tree& res, DfsColl items, std::optional<std::string> ignoredXPathPrefix);
114template
115void lyNodesToTree<libyang::Set<libyang::DataNode>>(DatastoreAccess::Tree& res, libyang::Set<libyang::DataNode> items, std::optional<std::string> ignoredXPathPrefix);
116
117DatastoreAccess::Tree rpcOutputToTree(libyang::DataNode output)
Václav Kubernátfbab2d42021-02-05 16:12:34 +0100118{
119 DatastoreAccess::Tree res;
Václav Kubernátcfdb9222021-07-07 22:36:24 +0200120 lyNodesToTree(res, output.siblings(), joinPaths(std::string{output.path()}, "/"));
Václav Kubernátfbab2d42021-02-05 16:12:34 +0100121 return res;
122}
123
Václav Kubernátcfdb9222021-07-07 22:36:24 +0200124libyang::DataNode treeToRpcInput(libyang::Context ctx, const std::string& path, DatastoreAccess::Tree in)
Václav Kubernátfbab2d42021-02-05 16:12:34 +0100125{
Jan Kundrátf59b83c2022-03-18 18:12:08 +0100126 auto root = ctx.newPath(path, std::nullopt, libyang::CreationOptions::Update);
Václav Kubernátfbab2d42021-02-05 16:12:34 +0100127 for (const auto& [k, v] : in) {
Jan Kundrátf59b83c2022-03-18 18:12:08 +0100128 root.newPath(k, leafDataToString(v), libyang::CreationOptions::Update);
Václav Kubernátfbab2d42021-02-05 16:12:34 +0100129 }
130
131 return root;
132}