Add datastore support for bits
Change-Id: I9a1619f6b892bbde71e75376e9a3a84911236b5d
diff --git a/src/ast_values.cpp b/src/ast_values.cpp
index c3f2ce7..da65d7c 100644
--- a/src/ast_values.cpp
+++ b/src/ast_values.cpp
@@ -35,6 +35,16 @@
empty_::empty_() = default;
+bool bits_::operator==(const bits_& other) const
+{
+ return this->m_bits == other.m_bits;
+}
+
+bool bits_::operator<(const bits_& other) const
+{
+ return this->m_bits < other.m_bits;
+}
+
bool module_::operator<(const module_& b) const
{
return this->m_name < b.m_name;
diff --git a/src/ast_values.hpp b/src/ast_values.hpp
index f790148..228aac3 100644
--- a/src/ast_values.hpp
+++ b/src/ast_values.hpp
@@ -9,6 +9,7 @@
#include <boost/optional.hpp>
#include <boost/variant.hpp>
+#include <set>
struct enum_ {
enum_();
@@ -32,6 +33,12 @@
bool operator<(const empty_) const;
};
+struct bits_ {
+ bool operator==(const bits_&) const;
+ bool operator<(const bits_&) const;
+ std::set<std::string> m_bits;
+};
+
struct module_ {
bool operator==(const module_& b) const;
bool operator<(const module_& b) const;
@@ -66,6 +73,7 @@
using leaf_data_ = boost::variant<enum_,
binary_,
empty_,
+ bits_,
identityRef_,
special_,
double,
diff --git a/src/libyang_utils.cpp b/src/libyang_utils.cpp
index 456fa62..840d413 100644
--- a/src/libyang_utils.cpp
+++ b/src/libyang_utils.cpp
@@ -36,6 +36,15 @@
return binary_{value->binary()};
case LY_TYPE_EMPTY:
return empty_{};
+ case LY_TYPE_BITS:
+ {
+ auto bits = value->bit();
+ std::vector<libyang::S_Type_Bit> filterNull;
+ std::copy_if(bits.begin(), bits.end(), std::back_inserter(filterNull), [] (auto bit) { return bit; });
+ bits_ res;
+ std::transform(filterNull.begin(), filterNull.end(), std::inserter(res.m_bits, res.m_bits.end()), [] (const auto& bit) { return bit->name(); });
+ return bits_{res};
+ }
case LY_TYPE_DEC64:
{
auto v = value->dec64();
diff --git a/src/sysrepo_access.cpp b/src/sysrepo_access.cpp
index e792ed8..205db3a 100644
--- a/src/sysrepo_access.cpp
+++ b/src/sysrepo_access.cpp
@@ -6,9 +6,11 @@
*
*/
+#include <experimental/iterator>
#include <libyang/Tree_Data.hpp>
#include <libyang/Tree_Schema.hpp>
#include <sysrepo-cpp/Session.hpp>
+#include <sstream>
#include "libyang_utils.hpp"
#include "sysrepo_access.hpp"
#include "utils.hpp"
@@ -57,6 +59,18 @@
return special_{SpecialValue::PresenceContainer};
case SR_LIST_T:
return special_{SpecialValue::List};
+ case SR_BITS_T:
+ {
+ bits_ res;
+ std::istringstream ss(value->data()->get_bits());
+ while (!ss.eof()) {
+ std::string bit;
+ ss >> bit;
+ res.m_bits.insert(bit);
+ }
+ return res;
+
+ }
default: // TODO: implement all types
return value->val_to_string();
}
@@ -94,6 +108,13 @@
return std::make_shared<sysrepo::Val>(value.c_str());
}
+ sysrepo::S_Val operator()(const bits_& value) const
+ {
+ std::stringstream ss;
+ std::copy(value.m_bits.begin(), value.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
+ return std::make_shared<sysrepo::Val>(ss.str().c_str(), SR_BITS_T);
+ }
+
template <typename T>
sysrepo::S_Val operator()(const T& value) const
{
@@ -144,6 +165,13 @@
}
}
+ auto operator()(const bits_& value) const
+ {
+ std::stringstream ss;
+ std::copy(value.m_bits.begin(), value.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
+ v->set(xpath.c_str(), ss.str().c_str(), SR_BITS_T);
+ }
+
void operator()(const std::string& value) const
{
v->set(xpath.c_str(), value.c_str(), SR_STRING_T);
diff --git a/src/utils.cpp b/src/utils.cpp
index b3d3601..11a97b4 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -196,6 +196,13 @@
}
}
+ std::string operator()(const bits_& data) const
+ {
+ std::stringstream ss;
+ std::copy(data.m_bits.begin(), data.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
+ return ss.str();
+ }
+
template <typename T>
std::string operator()(const T& data) const
{
diff --git a/tests/datastore_access.cpp b/tests/datastore_access.cpp
index da3bc48..022b115 100644
--- a/tests/datastore_access.cpp
+++ b/tests/datastore_access.cpp
@@ -508,6 +508,17 @@
REQUIRE(datastore.getItems("/example-schema:dummy") == expected);
}
+ SECTION("bits")
+ {
+ datastore.setLeaf("/example-schema:flags", bits_{{"sign", "carry"}});
+ REQUIRE_CALL(mock, write("/example-schema:flags", std::nullopt, "carry sign"s));
+ datastore.commitChanges();
+ DatastoreAccess::Tree expected {
+ {"/example-schema:flags", bits_{{"carry", "sign"}}},
+ };
+ REQUIRE(datastore.getItems("/example-schema:flags") == expected);
+ }
+
#if not defined(yang_BACKEND)
SECTION("operational data")
{
diff --git a/tests/example-schema.yang b/tests/example-schema.yang
index da45afd..372b83d 100644
--- a/tests/example-schema.yang
+++ b/tests/example-schema.yang
@@ -294,4 +294,13 @@
type int32;
}
}
+
+ leaf flags {
+ type bits {
+ bit carry;
+ bit zero;
+ bit sign;
+ bit parity;
+ }
+ }
}
diff --git a/tests/mock/sysrepo_subscription.cpp b/tests/mock/sysrepo_subscription.cpp
index c74d7af..ba276a7 100644
--- a/tests/mock/sysrepo_subscription.cpp
+++ b/tests/mock/sysrepo_subscription.cpp
@@ -6,6 +6,8 @@
*
*/
+#include <experimental/iterator>
+#include <sstream>
#include <sysrepo-cpp/Session.hpp>
#include "sysrepo_subscription.hpp"
@@ -94,6 +96,14 @@
v->set(xpath.c_str(), what.c_str());
}
+ void operator()(const bits_& what)
+ {
+ std::stringstream ss;
+ std::copy(what.m_bits.begin(), what.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
+ v->set(xpath.c_str(), ss.str().c_str());
+
+ }
+
template <typename Type>
void operator()(const Type what)
{
diff --git a/tests/pretty_printers.hpp b/tests/pretty_printers.hpp
index 6864443..ab6b917 100644
--- a/tests/pretty_printers.hpp
+++ b/tests/pretty_printers.hpp
@@ -42,7 +42,7 @@
{
s << "DatastoreAccess::Tree {\n";
for (const auto& [xpath, value] : tree) {
- s << " {" << xpath << ", " << leafDataToString(value) << "},\n";
+ s << " {" << xpath << ", " << boost::core::demangle(value.type().name()) << "{" << leafDataToString(value) << "}},\n";
}
s << "}\n";
return s;