Add support for leafrefs
Change-Id: I2286aaa96abd960d13bb0b04a778fb264b2f74a4
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 9fd65ff..5501247 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -428,7 +428,11 @@
leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
- if (schema.leafType(location, {module, leaf.m_name}) != m_type) {
+ auto type = schema.leafType(location, {module, leaf.m_name});
+ if (type == yang::LeafDataTypes::LeafRef) {
+ type = schema.leafrefBase(location, {module, leaf.m_name});
+ }
+ if (type != m_type) {
_pass(context) = false;
}
}
diff --git a/src/schema.hpp b/src/schema.hpp
index 64f743c..e0d30af 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -33,6 +33,7 @@
Enum,
Binary,
IdentityRef,
+ LeafRef,
};
}
@@ -73,6 +74,8 @@
virtual bool listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const = 0;
virtual const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const = 0;
virtual yang::LeafDataTypes leafType(const schemaPath_& location, const ModuleNodePair& node) const = 0;
+ virtual yang::LeafDataTypes leafrefBase(const schemaPath_& location, const ModuleNodePair& node) const = 0;
+
virtual const std::set<std::string> validIdentities(const schemaPath_& location, const ModuleNodePair& node, const Prefixes prefixes) const = 0;
virtual const std::set<std::string> enumValues(const schemaPath_& location, const ModuleNodePair& node) const = 0;
virtual std::set<std::string> childNodes(const schemaPath_& path, const Recursion recursion) const = 0;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
index 280f0da..3c3fced 100644
--- a/src/static_schema.cpp
+++ b/src/static_schema.cpp
@@ -105,7 +105,7 @@
void StaticSchema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type)
{
- m_nodes.at(location).emplace(name, yang::leaf{type, {}, {}});
+ m_nodes.at(location).emplace(name, yang::leaf{type, {}, {}, {}});
}
void StaticSchema::addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues)
@@ -125,6 +125,14 @@
m_nodes.at(location).emplace(name, toAdd);
}
+void StaticSchema::addLeafRef(const std::string& location, const std::string& name, const std::string& source)
+{
+ yang::leaf toAdd;
+ toAdd.m_type = yang::LeafDataTypes::LeafRef;
+ toAdd.m_leafRefSource = source;
+ m_nodes.at(location).emplace(name, toAdd);
+}
+
void StaticSchema::addModule(const std::string& name)
{
m_modules.emplace(name);
@@ -198,6 +206,24 @@
return children(locationString).at(fullName).type() == typeid(yang::leaf);
}
+std::string lastNodeOfSchemaPath(const std::string& path)
+{
+ std::string res = path;
+ auto pos = res.find_last_of('/');
+ if (pos != res.npos)
+ res.erase(0, pos);
+ return res;
+}
+
+yang::LeafDataTypes StaticSchema::leafrefBase(const schemaPath_& location, const ModuleNodePair& node) const
+{
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ auto leaf{boost::get<yang::leaf>(children(locationString).at(fullNodeName(location, node)))};
+ auto locationOfSource = stripLastNodeFromPath(leaf.m_leafRefSource);
+ auto nameOfSource = lastNodeOfSchemaPath(leaf.m_leafRefSource);
+ return boost::get<yang::leaf>(children(locationOfSource).at(nameOfSource)).m_type;
+}
+
yang::LeafDataTypes StaticSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
{
std::string locationString = pathToAbsoluteSchemaString(location);
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
index 4af6793..559be6c 100644
--- a/src/static_schema.hpp
+++ b/src/static_schema.hpp
@@ -30,6 +30,7 @@
yang::LeafDataTypes m_type;
std::set<std::string> m_enumValues;
ModuleValuePair m_identBase;
+ std::string m_leafRefSource;
};
struct module {
@@ -58,6 +59,7 @@
bool listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const override;
const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const override;
yang::LeafDataTypes leafType(const schemaPath_& location, const ModuleNodePair& node) const override;
+ yang::LeafDataTypes leafrefBase(const schemaPath_& location, const ModuleNodePair& node) const override;
const std::set<std::string> enumValues(const schemaPath_& location, const ModuleNodePair& node) const override;
const std::set<std::string> validIdentities(const schemaPath_& location, const ModuleNodePair& node, const Prefixes prefixes) const override;
std::set<std::string> childNodes(const schemaPath_& path, const Recursion) const override;
@@ -66,6 +68,7 @@
void addLeaf(const std::string& location, const std::string& name, const yang::LeafDataTypes& type);
void addLeafEnum(const std::string& location, const std::string& name, std::set<std::string> enumValues);
void addLeafIdentityRef(const std::string& location, const std::string& name, const ModuleValuePair& base);
+ void addLeafRef(const std::string& location, const std::string& name, const std::string& source);
void addList(const std::string& location, const std::string& name, const std::set<std::string>& keys);
void addModule(const std::string& name);
void addIdentity(const std::optional<ModuleValuePair>& base, const ModuleValuePair& name);
diff --git a/src/utils.cpp b/src/utils.cpp
index d06d35b..979bda4 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -62,6 +62,8 @@
return "an enum";
case yang::LeafDataTypes::IdentityRef:
return "an identity";
+ case yang::LeafDataTypes::LeafRef:
+ return "a leafref";
default:
throw std::runtime_error("leafDataTypeToString: unsupported leaf data type");
}
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 5f8a8cf..629aa2b 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -233,14 +233,9 @@
return keys;
}
-yang::LeafDataTypes YangSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
+yang::LeafDataTypes lyTypeToLeafDataTypes(LY_DATA_TYPE type)
{
- using namespace std::string_literals;
- if (!isLeaf(location, node))
- throw InvalidSchemaQueryException(fullNodeName(location, node) + " is not a leaf");
-
- libyang::Schema_Node_Leaf leaf(getSchemaNode(location, node));
- switch (leaf.type()->base()) {
+ switch (type) {
case LY_TYPE_STRING:
return yang::LeafDataTypes::String;
case LY_TYPE_DEC64:
@@ -269,8 +264,38 @@
return yang::LeafDataTypes::Binary;
case LY_TYPE_IDENT:
return yang::LeafDataTypes::IdentityRef;
+ case LY_TYPE_LEAFREF:
+ return yang::LeafDataTypes::LeafRef;
default:
- throw UnsupportedYangTypeException("the type of "s + fullNodeName(location, node) + " is not supported");
+ using namespace std::string_literals;
+ throw std::logic_error{"internal error: unsupported libyang data type "s + std::to_string(type)};
+ }
+
+}
+
+yang::LeafDataTypes YangSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
+{
+ using namespace std::string_literals;
+ if (!isLeaf(location, node))
+ throw InvalidSchemaQueryException(fullNodeName(location, node) + " is not a leaf");
+
+ libyang::Schema_Node_Leaf leaf(getSchemaNode(location, node));
+ auto baseType{leaf.type()->base()};
+ try {
+ return lyTypeToLeafDataTypes(baseType);
+ } catch(std::logic_error& ex) {
+ throw UnsupportedYangTypeException("the type of "s + fullNodeName(location, node) + " is not supported: " + ex.what());
+ }
+}
+
+yang::LeafDataTypes YangSchema::leafrefBase(const schemaPath_& location, const ModuleNodePair & node) const
+{
+ using namespace std::string_literals;
+ libyang::Schema_Node_Leaf leaf(getSchemaNode(location, node));
+ try {
+ return lyTypeToLeafDataTypes(leaf.type()->info()->lref()->target()->type()->base());
+ } catch(std::logic_error& ex) {
+ throw UnsupportedYangTypeException("the type of "s + fullNodeName(location, node) + " is not supported: " + ex.what());
}
}
diff --git a/src/yang_schema.hpp b/src/yang_schema.hpp
index 3621c17..fb4b922 100644
--- a/src/yang_schema.hpp
+++ b/src/yang_schema.hpp
@@ -40,6 +40,7 @@
bool listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const override;
const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const override;
yang::LeafDataTypes leafType(const schemaPath_& location, const ModuleNodePair& node) const override;
+ yang::LeafDataTypes leafrefBase(const schemaPath_& location, const ModuleNodePair& node) const override;
const std::set<std::string> validIdentities(const schemaPath_& location, const ModuleNodePair& node, const Prefixes prefixes) const override;
const std::set<std::string> enumValues(const schemaPath_& location, const ModuleNodePair& node) const override;
std::set<std::string> childNodes(const schemaPath_& path, const Recursion recursion) const override;
diff --git a/tests/leaf_editing.cpp b/tests/leaf_editing.cpp
index b0db594..bcf06aa 100644
--- a/tests/leaf_editing.cpp
+++ b/tests/leaf_editing.cpp
@@ -48,6 +48,8 @@
schema->addLeaf("mod:contA", "mod:leafInCont", yang::LeafDataTypes::String);
schema->addList("", "mod:list", {"number"});
schema->addLeaf("mod:list", "mod:leafInList", yang::LeafDataTypes::String);
+ schema->addLeafRef("", "mod:refToString", "mod:leafString");
+ schema->addLeafRef("", "mod:refToInt8", "mod:leafInt8");
Parser parser(schema);
std::string input;
std::ostringstream errorStream;
@@ -271,6 +273,22 @@
}
}
}
+ SECTION("leafRef")
+ {
+ SECTION("refToString")
+ {
+ input = "set mod:refToString blabal";
+ expected.m_path.m_nodes.push_back(dataNode_{module_{"mod"}, leaf_("refToString")});
+ expected.m_data = std::string("blabal");
+ }
+
+ SECTION("refToInt8")
+ {
+ input = "set mod:refToInt8 42";
+ expected.m_path.m_nodes.push_back(dataNode_{module_{"mod"}, leaf_("refToInt8")});
+ expected.m_data = int8_t{42};
+ }
+ }
}
command_ command = parser.parseCommand(input, errorStream);
@@ -359,6 +377,10 @@
{
input = "set leafEnum blabla";
}
+ SECTION("set mod:refToInt8 blabla")
+ {
+ input = "set mod:refToInt8 blabla";
+ }
}
SECTION("wrong base64 strings")