Add support for union leafs
Change-Id: Ifc1a53eed2c059f6fe5d75544ecaa3e63028f78f
diff --git a/src/leaf_data.hpp b/src/leaf_data.hpp
index 7139fc4..1c4176e 100644
--- a/src/leaf_data.hpp
+++ b/src/leaf_data.hpp
@@ -173,6 +173,12 @@
{
return std::visit(*this, *leafRef.m_targetType);
}
+ bool operator()(const yang::Union& unionInfo) const
+ {
+ return std::any_of(unionInfo.m_unionTypes.begin(), unionInfo.m_unionTypes.end(), [this](const auto& type) {
+ return std::visit(*this, type);
+ });
+ }
};
struct LeafData : x3::parser<LeafData> {
diff --git a/src/leaf_data_type.cpp b/src/leaf_data_type.cpp
index 815d0aa..8048efa 100644
--- a/src/leaf_data_type.cpp
+++ b/src/leaf_data_type.cpp
@@ -39,6 +39,10 @@
{
return this->m_targetXPath == other.m_targetXPath && *this->m_targetType == *other.m_targetType;
}
+bool Union::operator==(const Union& other) const
+{
+ return this->m_unionTypes == other.m_unionTypes;
+}
bool String::operator==(const String&) const
{
return true;
diff --git a/src/leaf_data_type.hpp b/src/leaf_data_type.hpp
index 66f4522..a86691b 100644
--- a/src/leaf_data_type.hpp
+++ b/src/leaf_data_type.hpp
@@ -10,6 +10,7 @@
#include <set>
#include <string>
#include <variant>
+#include <vector>
struct enum_;
struct identityRef_;
@@ -62,6 +63,7 @@
std::set<identityRef_> m_allowedValues;
};
struct LeafRef;
+struct Union;
using LeafDataType = std::variant<
yang::String,
yang::Decimal,
@@ -77,7 +79,8 @@
yang::Enum,
yang::Binary,
yang::IdentityRef,
- yang::LeafRef
+ yang::LeafRef,
+ yang::Union
>;
struct LeafRef {
LeafRef(const LeafRef& src);
@@ -86,4 +89,9 @@
std::string m_targetXPath;
std::unique_ptr<LeafDataType> m_targetType;
};
+
+struct Union {
+ bool operator==(const Union& other) const;
+ std::vector<LeafDataType> m_unionTypes;
+};
}
diff --git a/src/utils.cpp b/src/utils.cpp
index 719f28b..31854b2 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -5,6 +5,7 @@
* Written by Václav Kubernát <kubervac@fit.cvut.cz>
*
*/
+#include <experimental/iterator>
#include <sstream>
#include "completion.hpp"
#include "utils.hpp"
@@ -113,6 +114,14 @@
{
return "a leafref";
}
+ std::string operator()(const yang::Union& type)
+ {
+ std::ostringstream ss;
+ std::transform(type.m_unionTypes.begin(), type.m_unionTypes.end(), std::experimental::make_ostream_joiner(ss, ", "), [this](const auto& unionType) {
+ return std::visit(*this, unionType);
+ });
+ return ss.str();
+ }
};
std::string leafDataTypeToString(const yang::LeafDataType& type)
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 0f1a3fd..a453b50 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -154,9 +154,9 @@
}
namespace {
-std::set<enum_> enumValues(const libyang::S_Schema_Node_Leaf& leaf)
+std::set<enum_> enumValues(const libyang::S_Type& typeArg)
{
- auto type = leaf->type();
+ auto type = typeArg;
auto enm = type->info()->enums()->enm();
// The enum can be a derived type and enm() only returns values,
// if that specific typedef changed the possible values. So we go
@@ -177,13 +177,13 @@
return enumSet;
}
-std::set<identityRef_> validIdentities(const libyang::S_Schema_Node_Leaf& leaf)
+std::set<identityRef_> validIdentities(const libyang::S_Type& type)
{
std::set<identityRef_> identSet;
// auto topLevelModule = leaf->module();
- auto info = leaf->type()->info();
+ auto info = type->info();
for (auto base : info->ident()->ref()) { // Iterate over all bases
identSet.emplace(base->module()->name(), base->name());
// Iterate over derived identities (this is recursive!)
@@ -195,9 +195,9 @@
return identSet;
}
-std::string leafrefPath(const libyang::S_Schema_Node_Leaf& leaf)
+std::string leafrefPath(const libyang::S_Type& type)
{
- return leaf->type()->info()->lref()->target()->path(LYS_PATH_FIRST_PREFIX);
+ return type->info()->lref()->target()->path(LYS_PATH_FIRST_PREFIX);
}
}
@@ -205,42 +205,53 @@
{
using namespace std::string_literals;
auto leaf = std::make_shared<libyang::Schema_Node_Leaf>(node);
- auto baseType{leaf->type()->base()};
- switch (baseType) {
- case LY_TYPE_STRING:
- return yang::String{};
- case LY_TYPE_DEC64:
- return yang::Decimal{};
- case LY_TYPE_BOOL:
- return yang::Bool{};
- case LY_TYPE_INT8:
- return yang::Int8{};
- case LY_TYPE_INT16:
- return yang::Int16{};
- case LY_TYPE_INT32:
- return yang::Int32{};
- case LY_TYPE_INT64:
- return yang::Int64{};
- case LY_TYPE_UINT8:
- return yang::Uint8{};
- case LY_TYPE_UINT16:
- return yang::Uint16{};
- case LY_TYPE_UINT32:
- return yang::Uint32{};
- case LY_TYPE_UINT64:
- return yang::Uint64{};
- case LY_TYPE_BINARY:
- return yang::Binary{};
- case LY_TYPE_ENUM:
- return yang::Enum{enumValues(leaf)};
- case LY_TYPE_IDENT:
- return yang::IdentityRef{validIdentities(leaf)};
- case LY_TYPE_LEAFREF:
- return yang::LeafRef{::leafrefPath(leaf), std::make_unique<yang::LeafDataType>(leafType(::leafrefPath(leaf)))};
- default:
- using namespace std::string_literals;
- throw UnsupportedYangTypeException("the type of "s + node->name() + " is not supported: " + std::to_string(baseType));
- }
+ std::function<yang::LeafDataType(std::shared_ptr<libyang::Type>)> resolveType;
+ resolveType = [this, &resolveType, leaf] (auto type) -> yang::LeafDataType {
+ switch (type->base()) {
+ case LY_TYPE_STRING:
+ return yang::String{};
+ case LY_TYPE_DEC64:
+ return yang::Decimal{};
+ case LY_TYPE_BOOL:
+ return yang::Bool{};
+ case LY_TYPE_INT8:
+ return yang::Int8{};
+ case LY_TYPE_INT16:
+ return yang::Int16{};
+ case LY_TYPE_INT32:
+ return yang::Int32{};
+ case LY_TYPE_INT64:
+ return yang::Int64{};
+ case LY_TYPE_UINT8:
+ return yang::Uint8{};
+ case LY_TYPE_UINT16:
+ return yang::Uint16{};
+ case LY_TYPE_UINT32:
+ return yang::Uint32{};
+ case LY_TYPE_UINT64:
+ return yang::Uint64{};
+ case LY_TYPE_BINARY:
+ return yang::Binary{};
+ case LY_TYPE_ENUM:
+ return yang::Enum{enumValues(type)};
+ case LY_TYPE_IDENT:
+ return yang::IdentityRef{validIdentities(type)};
+ case LY_TYPE_LEAFREF:
+ return yang::LeafRef{::leafrefPath(type), std::make_unique<yang::LeafDataType>(leafType(::leafrefPath(type)))};
+ case LY_TYPE_UNION:
+ {
+ auto res = yang::Union{};
+ for (auto unionType : type->info()->uni()->types()) {
+ res.m_unionTypes.push_back(resolveType(unionType));
+ }
+ return res;
+ }
+ default:
+ using namespace std::string_literals;
+ throw UnsupportedYangTypeException("the type of "s + leaf->name() + " is not supported: " + std::to_string(leaf->type()->base()));
+ }
+ };
+ return resolveType(leaf->type());
}
yang::LeafDataType YangSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const