]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
sysrepo-lua: ported structural binding from sysrepo-bench branch
authorVasek Sraier <git@vakabus.cz>
Sun, 26 Apr 2020 20:38:06 +0000 (22:38 +0200)
committerAleš <ales.mrazek@nic.cz>
Mon, 20 Jul 2020 14:54:41 +0000 (16:54 +0200)
modules/sysrepo-lua/cbindings/sysrepo_clib.c
modules/sysrepo-lua/cbindings/sysrepo_clib.h
modules/sysrepo-lua/debug.lua
modules/sysrepo-lua/ffi.lua.in
modules/sysrepo-lua/model.lua

index 6aabf9ffc1fada694af6812d60c49676e5a421b4..60bd1eeb7f672d8b496bfc9b84a50e96dfa65e9c 100644 (file)
@@ -316,3 +316,41 @@ KR_EXPORT int node_validate(struct lyd_node* node) {
 KR_EXPORT void node_free(struct lyd_node* node) {
        lyd_free_withsiblings(node);
 }
+
+KR_EXPORT bool node_is_list_item(struct lyd_node* node) {
+       assert(node != NULL);
+
+       return node->schema->nodetype == LYS_LIST || node->schema->nodetype == LYS_LEAFLIST;
+}
+
+KR_EXPORT bool node_is_container(struct lyd_node* node) {
+       assert(node != NULL);
+
+       return node->schema->nodetype == LYS_CONTAINER;
+}
+
+KR_EXPORT bool node_is_leaf(struct lyd_node* node) {
+       assert(node != NULL);
+
+       return node->schema->nodetype == LYS_LEAF || node->schema->nodetype == LYS_LEAFLIST;
+}
+
+KR_EXPORT bool node_is_number_type(struct lyd_node* node) {
+       assert(node != NULL);
+       assert(node->schema->nodetype == LYS_LEAF || node->schema->nodetype == LYS_LEAFLIST);
+
+       LY_DATA_TYPE type = ((struct lyd_node_leaf_list*) node)->value_type;
+       switch (type) {
+               case LY_TYPE_INT8:
+               case LY_TYPE_UINT8:
+               case LY_TYPE_INT16:
+               case LY_TYPE_UINT16:
+               case LY_TYPE_INT32:
+               case LY_TYPE_UINT32:
+               case LY_TYPE_INT64:
+               case LY_TYPE_UINT64:
+                       return true;
+               default:
+                       return false;
+       }
+}
index 709c806aaf985fd51fd5b1c7a2be15594cc8ae50..398f1bb8355d34af88615b9e59d46d16c6edd06c 100644 (file)
@@ -76,3 +76,13 @@ KR_EXPORT const struct lys_node* schema_root();
 KR_EXPORT int node_validate(struct lyd_node* node);
 /** Free data nodes recursively */
 KR_EXPORT void node_free(struct lyd_node* node);
+/** Returns true when a data node is a list item */
+KR_EXPORT bool node_is_list_item(struct lyd_node* node);
+/** Returns true when a data node is a container */
+KR_EXPORT bool node_is_container(struct lyd_node* node);
+/** Returns true when a data node is a leaf node */
+KR_EXPORT bool node_is_leaf(struct lyd_node* node);
+/** Returns true when the given data node contains a number */
+KR_EXPORT bool node_is_number_type(struct lyd_node* node);
+
+
index ca68a5653dad162881d762c65e869432e1d914e5..805aaf207ff2112ceedcdf655cebcb01f68badd5 100644 (file)
@@ -20,4 +20,26 @@ function debug.log(msg, ...)
     print("[LUA DEBUG] " .. msg)
 end
 
+function debug.dump_table(table, indent)
+    if indent == nil then indent = 0 end
+
+    if table == nil then
+        debug.log("table is nil")
+        return
+    end
+
+    if indent == 0 then debug.log("{") end
+    for k,v in pairs(table) do
+        local space = string.rep(' ', (indent+1)*2)
+        if type(v) == 'table' then
+            debug.log(space .. "[" .. tostring(k) .. "] = {")
+            debug.dump_table(v, indent+1)
+            debug.log(space .. "},")
+        else
+            debug.log(space .. "[" .. tostring(k) .. "] = \"" .. tostring(v) .. "\", -- (" .. type(v) .. ")")
+        end
+    end
+    if indent == 0 then debug.log("}") end
+end
+
 return debug
index 31ac55c873c6a5944e57c032caf1b8711167496e..312913b3b220544f3eb707742c17d0138fbbfdbe 100644 (file)
@@ -46,6 +46,13 @@ local function initialize_ffi()
         int node_validate(struct lyd_node* node);
         /** Free data nodes recursively */
         void node_free(struct lyd_node* node);
+        /** Returns true when a data node is a list item */
+        bool node_is_list_item(struct lyd_node* node);
+        /** Returns true when a data node is a container */
+        bool node_is_container(struct lyd_node* node);
+        bool node_is_leaf(struct lyd_node* node);
+        /** Returns true when the given data node contains a number */
+        bool node_is_number_type(struct lyd_node* node);
     ]]
 end
 
index d599b6b7a0bc8fbfddbd5f3022ac4fc75f1e57c6..c3ce9a023ca4226a81d20e0d90b98648a1943313 100644 (file)
@@ -1,5 +1,6 @@
 local debug = require("kres_modules/sysrepo-lua/debug")
 local ffi = require("ffi")
+local os = require("os")
 
 local _clib = nil
 
@@ -24,6 +25,85 @@ function Helpers.get_children_table(node)
     return lookup
 end
 
+function Helpers.node_to_table(node)
+    if node == nil then
+        return nil
+    end
+
+    if clib().node_is_leaf(node) then
+        -- is primitive
+
+        if clib().node_is_number_type(node) then
+            return tonumber(ffi.string(clib().node_get_value_str(node)))
+        else
+            return ffi.string(clib().node_get_value_str(node))
+        end
+    else
+        -- is composite
+        local result = {}
+        local child = clib().node_child_first(node)
+        while child ~= nil do
+            local nm = ffi.string(clib().node_get_name(child))
+
+            if clib().node_is_list_item(child) then
+                if result[nm] == nil then
+                    result[nm] = {}
+                end
+
+                table.insert(result[nm], Helpers.node_to_table(child))
+            else
+                result[nm] = Helpers.node_to_table(child)
+            end
+
+            child = clib().node_child_next(child)
+        end
+
+        return result
+    end
+end
+
+function Helpers.object_to_node(object, name, schema_node, parent_node)
+    if object == nil then
+        return nil
+    end
+
+    assert(schema_node ~= nil)
+    assert(parent_node ~= nil)
+    assert(type(name) == "string")
+    assert(name == ffi.string(clib().schema_get_name(schema_node)))
+
+    if type(object) ~= "table" then
+        -- primitive
+        return clib().node_new_leaf(parent_node, clib().schema_get_module(schema_node), name, tostring(object))
+    else
+        -- composite
+
+        if object[1] ~= nil then
+            -- list
+            local last = nil
+            for _,v in ipairs(object) do
+                last = Helpers.object_to_node(v, name, schema_node, parent_node)
+            end
+            return last
+        else
+            -- container
+
+            local cont = clib().node_new_container(parent_node, clib().schema_get_module(schema_node), name)
+            local child_schema_nodes = Helpers.get_schema_children_table(schema_node)
+            for k,v in pairs(object) do
+                assert(type(k) == "string")
+
+                if child_schema_nodes[k] == nil then
+                    debug.log("Warning while serializing table - unknown child with name {}. Schema does not correspond.", k)
+                else
+                    Helpers.object_to_node(v, k, child_schema_nodes[k], cont)
+                end
+            end
+            return cont
+        end
+    end
+end
+
 function Helpers.get_children_str_values(node)
     local children = Helpers.get_children_table(node)
 
@@ -113,6 +193,7 @@ function Node:create(name, apply_func, read_func, initialize_schema_func)
     handler.serialize = read_func
     handler.name = name
     handler.module = nil -- must be filled in later by initialize_schema method
+    handler.schema = nil -- must be filled in later by initialize_schema method
 
     -- default implementation
     local function schema_init(self, lys_node)
@@ -120,6 +201,7 @@ function Node:create(name, apply_func, read_func, initialize_schema_func)
                                                             .. " (or something else happened).")
         assert(ffi.string(clib().schema_get_name(lys_node)) == self.name)
         self.module = clib().schema_get_module(lys_node)
+        self.schema = lys_node
     end
     if initialize_schema_func == nil then
         initialize_schema_func = schema_init
@@ -357,6 +439,40 @@ local function ConfigVarNode(name, type, bind_variable)
     return BindNode(name, type, get_val, set_val)
 end
 
+--- Node used for binding values
+---
+--- @param name Name of the vertex for constructing XPath
+--- @param type Type of the binded value as a string
+--- @param get_val Function that returns value with proper type, provides current state of the resolver.
+--- @param set_val Function with one argument of appropriate type, configures resolver
+local function StructuralBindNode(name, get_val, set_val)
+    --- Node's apply function
+    local function handle_apply(self, node)
+        -- do nothing when there is no set func
+        if set_val == nil then
+            return
+        end
+
+        -- obtain value from the lyd_node according to specified type
+        local val = Helpers.node_to_table(node)
+
+        -- set the value
+        set_val(val)
+    end
+
+    --- Node's serialize function
+    local function handle_serialize(self, parent_node)
+        if get_val == nil then
+            return nil
+        end
+
+        local val = get_val()
+        return Helpers.object_to_node(val, name, self.schema, parent_node)
+    end
+
+    return Node:create(name, handle_apply, handle_serialize, nil)
+end
+
 --- Binding node that binds whole container instead of single values.
 --- Works with one level deep containers.
 ---
@@ -536,7 +652,6 @@ local model =
         }, Hook:create(hook_apply_pre_network, nil))),
     })
 
-
 -------------------------------------------------------------------------------
 ------------------------ Module Exports ---------------------------------------
 -------------------------------------------------------------------------------
@@ -594,6 +709,7 @@ return function(clib_binding)
 
     function module.apply_configuration(root_node)
         init_schema()
+
         model:apply(root_node)
     end