Migrate to libyang2
libnetconf2: getSchema and getConfig were no longer used in netconf-cli,
so I deleted them. They can get readded once the bindings get split into
a separate project.
sysrepo_access: Some sr_val stuff was removed.
YangSchema: type descriptions are not available
availableNodes returns only input nodes for RPC nodes
impl_getSchemaNode: no longer disables error printing
libyang: No longer supports leafrefs without the leaf it points to.
Depends-on: https://cesnet-gerrit-czechlight/c/CzechLight/dependencies/+/5171
Depends-on: https://gerrit.cesnet.cz/c/CzechLight/dependencies/+/5171
Change-Id: Ie49381a003a61a7bb028be7b2fa1d9d926ac4e58
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index b964d31..f96aa46 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -6,9 +6,8 @@
*
*/
-#include <libyang/Libyang.hpp>
-#include <libyang/Tree_Data.hpp>
-#include <libyang/Tree_Schema.hpp>
+#include <libyang-cpp/Enum.hpp>
+#include <libyang-cpp/Utils.hpp>
#include <string_view>
#include "UniqueResource.hpp"
#include "utils.hpp"
@@ -33,11 +32,11 @@
};
YangSchema::YangSchema()
- : m_context(std::make_shared<libyang::Context>(nullptr, LY_CTX_DISABLE_SEARCHDIR_CWD))
+ : m_context(nullptr, libyang::ContextOptions::DisableSearchDirs | libyang::ContextOptions::SetPrivParsed)
{
}
-YangSchema::YangSchema(std::shared_ptr<libyang::Context> lyCtx)
+YangSchema::YangSchema(libyang::Context lyCtx)
: m_context(lyCtx)
{
}
@@ -46,29 +45,22 @@
void YangSchema::addSchemaString(const char* schema)
{
- if (!m_context->parse_module_mem(schema, LYS_IN_YANG)) {
- throw YangLoadError("Couldn't load schema");
- }
+ m_context.parseModuleMem(schema, libyang::SchemaFormat::YANG);
}
void YangSchema::addSchemaDirectory(const char* directoryName)
{
- if (m_context->set_searchdir(directoryName)) {
- throw YangLoadError("Couldn't add schema search directory");
- }
+ m_context.setSearchDir(directoryName);
}
void YangSchema::addSchemaFile(const char* filename)
{
- if (!m_context->parse_module_path(filename, LYS_IN_YANG)) {
- throw YangLoadError("Couldn't load schema");
- }
+ m_context.parseModulePath(filename, libyang::SchemaFormat::YANG);
}
bool YangSchema::isModule(const std::string& name) const
{
- const auto set = modules();
- return set.find(name) != set.end();
+ return m_context.getModuleImplemented(name.c_str()).has_value();
}
bool YangSchema::listHasKey(const schemaPath_& listPath, const std::string& key) const
@@ -80,49 +72,52 @@
bool YangSchema::leafIsKey(const std::string& leafPath) const
{
auto node = getSchemaNode(leafPath);
- if (!node || node->nodetype() != LYS_LEAF) {
+ if (!node || node->nodeType() != libyang::NodeType::Leaf) {
return false;
}
- return libyang::Schema_Node_Leaf{node}.is_key().get();
+ return node->asLeaf().isKey();
}
-libyang::S_Schema_Node YangSchema::impl_getSchemaNode(const std::string& node) const
+std::optional<libyang::SchemaNode> YangSchema::impl_getSchemaNode(const std::string& node) const
{
- // If no node is found find_path prints an error message, so we have to
- // disable logging
- // https://github.com/CESNET/libyang/issues/753
- {
- int oldOptions;
- auto logBlocker = make_unique_resource(
- [&oldOptions]() {
- oldOptions = libyang::set_log_options(0);
- },
- [&oldOptions]() {
- libyang::set_log_options(oldOptions);
- });
- auto res = m_context->get_node(nullptr, node.c_str());
- if (!res) { // If no node is found, try output rpc nodes too.
- res = m_context->get_node(nullptr, node.c_str(), 1);
+ // libyang::Context::findPath throws an exception, when no matching schema node is found. This exception has the
+ // ValidationFailure error code. We will catch that exception (and rethrow if it's not the correct error code.
+ //
+ // Also, we need to use findPath twice if we're trying to find output nodes.
+ try {
+ return m_context.findPath(node.c_str());
+ } catch (libyang::ErrorWithCode& err) {
+ if (err.code() != libyang::ErrorCode::ValidationFailure) {
+ throw;
}
- return res;
}
+ try {
+ return m_context.findPath(node.c_str(), libyang::OutputNodes::Yes);
+ } catch (libyang::ErrorWithCode& err) {
+ if (err.code() != libyang::ErrorCode::ValidationFailure) {
+ throw;
+ }
+ }
+
+ // We didn't find a matching node.
+ return std::nullopt;
}
-libyang::S_Schema_Node YangSchema::getSchemaNode(const std::string& node) const
+std::optional<libyang::SchemaNode> YangSchema::getSchemaNode(const std::string& node) const
{
return impl_getSchemaNode(node);
}
-libyang::S_Schema_Node YangSchema::getSchemaNode(const schemaPath_& location, const ModuleNodePair& node) const
+std::optional<libyang::SchemaNode> YangSchema::getSchemaNode(const schemaPath_& location, const ModuleNodePair& node) const
{
std::string absPath = joinPaths(pathToSchemaString(location, Prefixes::Always), fullNodeName(location, node));
return impl_getSchemaNode(absPath);
}
-libyang::S_Schema_Node YangSchema::getSchemaNode(const schemaPath_& listPath) const
+std::optional<libyang::SchemaNode> YangSchema::getSchemaNode(const schemaPath_& listPath) const
{
std::string absPath = pathToSchemaString(listPath, Prefixes::Always);
return impl_getSchemaNode(absPath);
@@ -131,174 +126,121 @@
const std::set<std::string> YangSchema::listKeys(const schemaPath_& listPath) const
{
auto node = getSchemaNode(listPath);
- if (node->nodetype() != LYS_LIST) {
+ if (node->nodeType() != libyang::NodeType::List) {
return {};
}
- auto list = std::make_shared<libyang::Schema_Node_List>(node);
std::set<std::string> keys;
- const auto& keysVec = list->keys();
+ auto keysVec = node->asList().keys();
- std::transform(keysVec.begin(), keysVec.end(), std::inserter(keys, keys.begin()), [](const auto& it) { return it->name(); });
+ std::transform(keysVec.begin(), keysVec.end(), std::inserter(keys, keys.begin()), [](const auto& it) { return std::string{it.name()}; });
return keys;
}
-namespace {
-enum class ResolveMode {
- Enum,
- Identity
-};
-/** @brief Resolves a typedef to a type which defines values.
- * When we need allowed values of a type and that type is a typedef, we need to recurse into the typedef until we find a
- * type which defines values. These values are the allowed values.
- * Example:
- *
- * typedef MyOtherEnum {
- * type enumeration {
- * enum "A";
- * enum "B";
- * }
- * }
- *
- * typedef MyEnum {
- * type MyOtherEnum;
- * }
- *
- * If `toResolve` points to MyEnum, then just doing ->enums()->enm() returns nothing and that means that this particular
- * typedef (MyEnum) did not say which values are allowed. So, we need to dive into the parent enum (MyOtherEnum) with
- * ->der()->type(). This typedef (MyOtherEnum) DID specify allowed values and enums()->enm() WILL contain them. These
- * values are the only relevant values and we don't care about other parent typedefs. We return these values to the
- * caller.
- *
- * For enums, this function simply returns all allowed enums.
- * For identities, this function returns which bases `toResolve` has.
- */
-template <ResolveMode TYPE>
-auto resolveTypedef(const libyang::S_Type& toResolve)
+std::set<enum_> enumValues(const libyang::Type& type)
{
- auto type = toResolve;
- auto getValuesFromType = [] (const libyang::S_Type& type) {
- if constexpr (TYPE == ResolveMode::Identity) {
- return type->info()->ident()->ref();
- } else {
- return type->info()->enums()->enm();
- }
- };
- auto values = getValuesFromType(type);
- while (values.empty()) {
- type = type->der()->type();
- values = getValuesFromType(type);
- }
-
- return values;
-}
-
-std::set<enum_> enumValues(const libyang::S_Type& type)
-{
- auto values = resolveTypedef<ResolveMode::Enum>(type);
-
- std::vector<libyang::S_Type_Enum> enabled;
- std::copy_if(values.begin(), values.end(), std::back_inserter(enabled), [](const libyang::S_Type_Enum& it) {
- auto iffeatures = it->iffeature();
- return std::all_of(iffeatures.begin(), iffeatures.end(), [](auto it) { return it->value(); });
- });
-
+ auto enums = type.asEnum().items();
std::set<enum_> enumSet;
- std::transform(enabled.begin(), enabled.end(), std::inserter(enumSet, enumSet.end()), [](auto it) { return enum_{it->name()}; });
+ std::transform(enums.begin(), enums.end(), std::inserter(enumSet, enumSet.end()), [](auto it) { return enum_{std::string{it.name}}; });
return enumSet;
}
-std::set<identityRef_> validIdentities(const libyang::S_Type& type)
+std::set<identityRef_> validIdentities(const libyang::Type& type)
{
std::set<identityRef_> identSet;
- for (auto base : resolveTypedef<ResolveMode::Identity>(type)) { // Iterate over all bases
- // Iterate over derived identities (this is recursive!)
- if (auto der = base->der()) {
- for (auto derived : der->schema()) {
- identSet.emplace(derived->module()->name(), derived->name());
- }
+ std::function<void(const std::vector<libyang::Identity>&)> impl = [&identSet, &impl] (const std::vector<libyang::Identity>& idents) {
+ if (idents.empty()) {
+ return;
}
+
+ for (const auto& ident : idents) {
+ identSet.emplace(std::string{ident.module().name()}, std::string{ident.name()});
+ impl(ident.derived());
+ }
+ };
+
+ for (const auto& base : type.asIdentityRef().bases()) {
+ impl(base.derived());
}
return identSet;
}
-std::string leafrefPath(const libyang::S_Type& type)
+std::string leafrefPath(const libyang::Type& type)
{
- return type->info()->lref()->target()->path(LYS_PATH_FIRST_PREFIX);
-}
+ return std::string{type.asLeafRef().path()};
}
template <typename NodeType>
-yang::TypeInfo YangSchema::impl_leafType(const libyang::S_Schema_Node& node) const
+yang::TypeInfo YangSchema::impl_leafType(const NodeType& node) const
{
using namespace std::string_literals;
auto leaf = std::make_shared<NodeType>(node);
auto leafUnits = leaf->units();
- std::function<yang::TypeInfo(std::shared_ptr<libyang::Type>)> resolveType;
- resolveType = [this, &resolveType, leaf, leafUnits](std::shared_ptr<libyang::Type> type) -> yang::TypeInfo {
+ std::function<yang::TypeInfo(const libyang::Type&)> resolveType;
+ resolveType = [&resolveType, leaf, leafUnits](const libyang::Type& type) -> yang::TypeInfo {
yang::LeafDataType resType;
- switch (type->base()) {
- case LY_TYPE_STRING:
+ switch (type.base()) {
+ case libyang::LeafBaseType::String:
resType.emplace<yang::String>();
break;
- case LY_TYPE_DEC64:
+ case libyang::LeafBaseType::Dec64:
resType.emplace<yang::Decimal>();
break;
- case LY_TYPE_BOOL:
+ case libyang::LeafBaseType::Bool:
resType.emplace<yang::Bool>();
break;
- case LY_TYPE_INT8:
+ case libyang::LeafBaseType::Int8:
resType.emplace<yang::Int8>();
break;
- case LY_TYPE_INT16:
+ case libyang::LeafBaseType::Int16:
resType.emplace<yang::Int16>();
break;
- case LY_TYPE_INT32:
+ case libyang::LeafBaseType::Int32:
resType.emplace<yang::Int32>();
break;
- case LY_TYPE_INT64:
+ case libyang::LeafBaseType::Int64:
resType.emplace<yang::Int64>();
break;
- case LY_TYPE_UINT8:
+ case libyang::LeafBaseType::Uint8:
resType.emplace<yang::Uint8>();
break;
- case LY_TYPE_UINT16:
+ case libyang::LeafBaseType::Uint16:
resType.emplace<yang::Uint16>();
break;
- case LY_TYPE_UINT32:
+ case libyang::LeafBaseType::Uint32:
resType.emplace<yang::Uint32>();
break;
- case LY_TYPE_UINT64:
+ case libyang::LeafBaseType::Uint64:
resType.emplace<yang::Uint64>();
break;
- case LY_TYPE_BINARY:
+ case libyang::LeafBaseType::Binary:
resType.emplace<yang::Binary>();
break;
- case LY_TYPE_EMPTY:
+ case libyang::LeafBaseType::Empty:
resType.emplace<yang::Empty>();
break;
- case LY_TYPE_ENUM:
+ case libyang::LeafBaseType::Enum:
resType.emplace<yang::Enum>(enumValues(type));
break;
- case LY_TYPE_IDENT:
+ case libyang::LeafBaseType::IdentityRef:
resType.emplace<yang::IdentityRef>(validIdentities(type));
break;
- case LY_TYPE_LEAFREF:
- resType.emplace<yang::LeafRef>(::leafrefPath(type), std::make_unique<yang::TypeInfo>(leafType(::leafrefPath(type))));
+ case libyang::LeafBaseType::Leafref:
+ resType.emplace<yang::LeafRef>(::leafrefPath(type), std::make_unique<yang::TypeInfo>(resolveType(type.asLeafRef().resolvedType())));
break;
- case LY_TYPE_BITS: {
+ case libyang::LeafBaseType::Bits: {
auto resBits = yang::Bits{};
- for (const auto& bit : type->info()->bits()->bit()) {
- resBits.m_allowedValues.emplace(bit->name());
+ for (const auto& bit : type.asBits().items()) {
+ resBits.m_allowedValues.emplace(std::string{bit.name});
}
resType.emplace<yang::Bits>(std::move(resBits));
break;
}
- case LY_TYPE_UNION: {
+ case libyang::LeafBaseType::Union: {
auto resUnion = yang::Union{};
- for (auto unionType : type->info()->uni()->types()) {
+ for (auto unionType : type.asUnion().types()) {
resUnion.m_unionTypes.emplace_back(resolveType(unionType));
}
resType.emplace<yang::Union>(std::move(resUnion));
@@ -306,48 +248,26 @@
}
default:
using namespace std::string_literals;
- throw UnsupportedYangTypeException("the type of "s + leaf->name() + " is not supported: " + std::to_string(leaf->type()->base()));
+ throw UnsupportedYangTypeException("the type of "s +
+ std::string{leaf->name()} +
+ " is not supported: " +
+ std::to_string(std::underlying_type_t<libyang::LeafBaseType>(leaf->valueType().base())));
}
- std::optional<std::string> resUnits;
- if (leafUnits) {
- resUnits = leafUnits;
- } else {
- for (auto parentTypedef = type->der(); parentTypedef; parentTypedef = parentTypedef->type()->der()) {
- auto units = parentTypedef->units();
- if (units) {
- resUnits = units;
- break;
- }
- }
- }
-
- std::optional<std::string> resDescription;
-
- // checking for parentTypedef->type()->der() means I'm going to enter inside base types like "string". These
- // also have a description, but it isn't too helpful ("human-readable string")
- for (auto parentTypedef = type->der(); parentTypedef && parentTypedef->type()->der(); parentTypedef = parentTypedef->type()->der()) {
- auto dsc = parentTypedef->dsc();
- if (dsc) {
- resDescription = dsc;
- break;
- }
- }
-
- return yang::TypeInfo(resType, resUnits, resDescription);
+ return yang::TypeInfo(resType, std::optional<std::string>{leafUnits}, std::optional<std::string>{type.description()});
};
- return resolveType(leaf->type());
+ return resolveType(leaf->valueType());
}
yang::TypeInfo YangSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
{
auto lyNode = getSchemaNode(location, node);
- switch (lyNode->nodetype()) {
- case LYS_LEAF:
- return impl_leafType<libyang::Schema_Node_Leaf>(lyNode);
- case LYS_LEAFLIST:
- return impl_leafType<libyang::Schema_Node_Leaflist>(lyNode);
+ switch (lyNode->nodeType()) {
+ case libyang::NodeType::Leaf:
+ return impl_leafType(lyNode->asLeaf());
+ case libyang::NodeType::Leaflist:
+ return impl_leafType(lyNode->asLeafList());
default:
throw std::logic_error("YangSchema::leafType: type must be leaf or leaflist");
}
@@ -356,11 +276,11 @@
yang::TypeInfo YangSchema::leafType(const std::string& path) const
{
auto lyNode = getSchemaNode(path);
- switch (lyNode->nodetype()) {
- case LYS_LEAF:
- return impl_leafType<libyang::Schema_Node_Leaf>(lyNode);
- case LYS_LEAFLIST:
- return impl_leafType<libyang::Schema_Node_Leaflist>(lyNode);
+ switch (lyNode->nodeType()) {
+ case libyang::NodeType::Leaf:
+ return impl_leafType(lyNode->asLeaf());
+ case libyang::NodeType::Leaflist:
+ return impl_leafType(lyNode->asLeafList());
default:
throw std::logic_error("YangSchema::leafType: type must be leaf or leaflist");
}
@@ -368,23 +288,22 @@
std::optional<std::string> YangSchema::leafTypeName(const std::string& path) const
{
- libyang::Schema_Node_Leaf leaf(getSchemaNode(path));
- return leaf.type()->der().get() && leaf.type()->der()->type()->der().get() ? std::optional{leaf.type()->der()->name()} : std::nullopt;
+ auto leaf = getSchemaNode(path)->asLeaf();
+ return std::string{leaf.valueType().name()};
}
std::string YangSchema::leafrefPath(const std::string& leafrefPath) const
{
using namespace std::string_literals;
- libyang::Schema_Node_Leaf leaf(getSchemaNode(leafrefPath));
- return leaf.type()->info()->lref()->target()->path(LYS_PATH_FIRST_PREFIX);
+ return ::leafrefPath(getSchemaNode(leafrefPath)->asLeaf().valueType());
}
std::set<std::string> YangSchema::modules() const
{
- const auto& modules = m_context->get_module_iter();
+ const auto& modules = m_context.modules();
std::set<std::string> res;
- std::transform(modules.begin(), modules.end(), std::inserter(res, res.end()), [](const auto module) { return module->name(); });
+ std::transform(modules.begin(), modules.end(), std::inserter(res, res.end()), [](const auto module) { return std::string{module.name()}; });
return res;
}
@@ -392,39 +311,49 @@
{
using namespace std::string_view_literals;
std::set<ModuleNodePair> res;
- std::vector<libyang::S_Schema_Node> nodes;
+ std::vector<libyang::ChildInstanstiables> nodeCollections;
std::string topLevelModule;
if (path.type() == typeid(module_)) {
- nodes = m_context->get_module(boost::get<module_>(path).m_name.c_str())->data_instantiables(0);
+ nodeCollections.emplace_back(m_context.getModule(boost::get<module_>(path).m_name.c_str())->childInstantiables());
} else {
auto schemaPath = anyPathToSchemaPath(path);
if (schemaPath.m_nodes.empty()) {
- nodes = m_context->data_instantiables(0);
+ for (const auto& module : m_context.modules()) {
+ if (module.implemented()) {
+ nodeCollections.emplace_back(module.childInstantiables());
+ }
+ }
} else {
const auto pathString = pathToSchemaString(schemaPath, Prefixes::Always);
const auto node = getSchemaNode(pathString);
- nodes = node->child_instantiables(0);
+ nodeCollections.emplace_back(node->childInstantiables());
topLevelModule = schemaPath.m_nodes.begin()->m_prefix->m_name;
}
}
- for (const auto& node : nodes) {
- if (node->module()->name() == "ietf-yang-library"sv) {
- continue;
- }
+ for (const auto& coll : nodeCollections) {
+ for (const auto& node : coll) {
+ if (node.module().name() == "ietf-yang-library"sv) {
+ continue;
+ }
- if (recursion == Recursion::Recursive) {
- for (auto it : node->tree_dfs()) {
- res.insert(ModuleNodePair(boost::none, it->path(LYS_PATH_FIRST_PREFIX)));
+ if (node.module().name() == "ietf-yang-schema-mount"sv) {
+ continue;
}
- } else {
- ModuleNodePair toInsert;
- if (topLevelModule.empty() || topLevelModule != node->module()->name()) {
- toInsert.first = node->module()->type() == 0 ? node->module()->name() : libyang::Submodule(node->module()).belongsto()->name();
+
+ if (recursion == Recursion::Recursive) {
+ for (auto it : node.childrenDfs()) {
+ res.insert(ModuleNodePair(boost::none, it.path()));
+ }
+ } else {
+ ModuleNodePair toInsert;
+ if (topLevelModule.empty() || topLevelModule != node.module().name()) {
+ toInsert.first = std::string{node.module().name()};
+ }
+ toInsert.second = node.name();
+ res.insert(toInsert);
}
- toInsert.second = node->name();
- res.insert(toInsert);
}
}
@@ -433,71 +362,81 @@
void YangSchema::loadModule(const std::string& moduleName)
{
- m_context->load_module(moduleName.c_str());
+ m_context.loadModule(moduleName.c_str());
}
-void YangSchema::enableFeature(const std::string& moduleName, const std::string& featureName)
+void YangSchema::setEnabledFeatures(const std::string& moduleName, const std::vector<std::string>& features)
{
using namespace std::string_literals;
auto module = getYangModule(moduleName);
if (!module) {
throw std::runtime_error("Module \""s + moduleName + "\" doesn't exist.");
}
- if (module->feature_enable(featureName.c_str())) {
- throw std::runtime_error("Can't enable feature \""s + featureName + "\" for module \"" + moduleName + "\".");
+ try {
+ module->setImplemented(features);
+ } catch (libyang::ErrorWithCode&) {
+ throw std::runtime_error("Can't enable features for module \"" + moduleName + "\".");
}
}
void YangSchema::registerModuleCallback(const std::function<std::string(const char*, const char*, const char*, const char*)>& clb)
{
- auto lambda = [clb](const char* mod_name, const char* mod_revision, const char* submod_name, const char* submod_revision) {
+ auto lambda = [clb](const char* mod_name, const char* mod_revision, const char* submod_name, const char* submod_revision) -> std::optional<libyang::ModuleInfo> {
(void)submod_revision;
auto moduleSource = clb(mod_name, mod_revision, submod_name, submod_revision);
if (moduleSource.empty()) {
- return libyang::Context::mod_missing_cb_return{LYS_IN_YANG, nullptr};
+ return std::nullopt;
}
- return libyang::Context::mod_missing_cb_return{LYS_IN_YANG, strdup(moduleSource.c_str())};
+ return libyang::ModuleInfo {
+ .data = moduleSource.c_str(),
+ .format = libyang::SchemaFormat::YANG
+
+ };
};
- m_context->add_missing_module_callback(lambda, free);
+ m_context.registerModuleCallback(lambda);
}
-std::shared_ptr<libyang::Data_Node> YangSchema::dataNodeFromPath(const std::string& path, const std::optional<const std::string> value) const
+libyang::CreatedNodes YangSchema::dataNodeFromPath(const std::string& path, const std::optional<const std::string> value) const
{
- return std::make_shared<libyang::Data_Node>(m_context,
- path.c_str(),
- value ? value.value().c_str() : nullptr,
- LYD_ANYDATA_CONSTSTRING,
- LYD_PATH_OPT_EDIT);
+ auto options = [this, &path, &value] {
+ // If we're creating a node without a value and it's not the "empty" type, then we also need the Opaque flag.
+ auto schema = getSchemaNode(path);
+ if (schema->nodeType() == libyang::NodeType::Leaf &&
+ schema->asLeaf().valueType().base() != libyang::LeafBaseType::Empty &&
+ !value) {
+ return std::optional<libyang::CreationOptions>{libyang::CreationOptions::Opaque};
+ }
+
+ return std::optional<libyang::CreationOptions>{};
+ }();
+ return m_context.newPath2(path.c_str(), value ? value->c_str() : nullptr, options);
}
-std::shared_ptr<libyang::Module> YangSchema::getYangModule(const std::string& name)
+std::optional<libyang::Module> YangSchema::getYangModule(const std::string& name)
{
- return m_context->get_module(name.c_str());
+ return m_context.getModuleImplemented(name.c_str());
}
namespace {
-yang::NodeTypes impl_nodeType(const libyang::S_Schema_Node& node)
+yang::NodeTypes impl_nodeType(const libyang::SchemaNode& node)
{
- if (!node) {
- throw InvalidNodeException();
- }
- switch (node->nodetype()) {
- case LYS_CONTAINER:
- return libyang::Schema_Node_Container{node}.presence() ? yang::NodeTypes::PresenceContainer : yang::NodeTypes::Container;
- case LYS_LEAF:
+ switch (node.nodeType()) {
+ case libyang::NodeType::Container:
+ return node.asContainer().isPresence() ? yang::NodeTypes::PresenceContainer : yang::NodeTypes::Container;
+ case libyang::NodeType::Leaf:
return yang::NodeTypes::Leaf;
- case LYS_LIST:
+ case libyang::NodeType::List:
return yang::NodeTypes::List;
- case LYS_RPC:
+ case libyang::NodeType::RPC:
return yang::NodeTypes::Rpc;
- case LYS_ACTION:
+ case libyang::NodeType::Action:
return yang::NodeTypes::Action;
- case LYS_NOTIF:
+ case libyang::NodeType::Notification:
return yang::NodeTypes::Notification;
- case LYS_ANYXML:
+ case libyang::NodeType::AnyXML:
return yang::NodeTypes::AnyXml;
- case LYS_LEAFLIST:
+ case libyang::NodeType::Leaflist:
return yang::NodeTypes::LeafList;
default:
throw InvalidNodeException(); // FIXME: Implement all types.
@@ -507,56 +446,57 @@
yang::NodeTypes YangSchema::nodeType(const schemaPath_& location, const ModuleNodePair& node) const
{
- return impl_nodeType(getSchemaNode(location, node));
+ return impl_nodeType(*getSchemaNode(location, node));
}
yang::NodeTypes YangSchema::nodeType(const std::string& path) const
{
- return impl_nodeType(getSchemaNode(path));
+ return impl_nodeType(*getSchemaNode(path));
}
std::optional<std::string> YangSchema::description(const std::string& path) const
{
- auto node = getSchemaNode(path.c_str());
- return node->dsc() ? std::optional{node->dsc()} : std::nullopt;
+ auto desc = getSchemaNode(path.c_str())->description();
+ return desc ? std::optional<std::string>{desc} : std::nullopt;
+
}
yang::Status YangSchema::status(const std::string& location) const
{
auto node = getSchemaNode(location.c_str());
- if (node->flags() & LYS_STATUS_DEPRC) {
+ switch (node->status()) {
+ case libyang::Status::Deprecated:
return yang::Status::Deprecated;
- } else if (node->flags() & LYS_STATUS_OBSLT) {
+ case libyang::Status::Obsolete:
return yang::Status::Obsolete;
- } else {
+ case libyang::Status::Current:
return yang::Status::Current;
}
+
+ __builtin_unreachable();
}
bool YangSchema::hasInputNodes(const std::string& path) const
{
auto node = getSchemaNode(path.c_str());
- if (auto type = node->nodetype(); type != LYS_ACTION && type != LYS_RPC) {
+ if (auto type = node->nodeType(); type != libyang::NodeType::Action && type != libyang::NodeType::RPC) {
throw std::logic_error("StaticSchema::hasInputNodes called with non-RPC/action path");
}
// The first child gives the /input node and then I check whether it has a child.
- return node->child()->child().get();
+ return node->child()->child().has_value();
}
bool YangSchema::isConfig(const std::string& path) const
{
auto node = getSchemaNode(path.c_str());
- if (node->flags() & LYS_CONFIG_W) {
- return true;
- }
-
- // Node can still be an input node.
- while (node->parent()) {
- node = node->parent();
- if (node->nodetype() == LYS_INPUT) {
+ try {
+ if (node->config() == libyang::Config::True) {
return true;
}
+ } catch (libyang::Error&) {
+ // For non-data nodes (like `rpc`), the config value can't be retrieved. In this case, we'll just default to
+ // "false".
}
return false;
@@ -564,22 +504,10 @@
std::optional<std::string> YangSchema::defaultValue(const std::string& leafPath) const
{
- libyang::Schema_Node_Leaf leaf(getSchemaNode(leafPath));
-
- if (auto leafDefault = leaf.dflt()) {
- return leafDefault;
- }
-
- for (auto type = leaf.type()->der(); type != nullptr; type = type->type()->der()) {
- if (auto defaultValue = type->dflt()) {
- return defaultValue;
- }
- }
-
- return std::nullopt;
+ return std::optional<std::string>{getSchemaNode(leafPath)->asLeaf().defaultValueStr()};
}
std::string YangSchema::dataPathToSchemaPath(const std::string& path)
{
- return getSchemaNode(path)->path(LYS_PATH_FIRST_PREFIX);
+ return std::string{getSchemaNode(path)->path()};
}