diff mbox series

[2/5] suricatta/lua: Fix and update specification + example

Message ID 20230602132022.70931-2-christian.storm@siemens.com
State Accepted
Headers show
Series [1/5] Lua/specs: Ignore missing returns diagnostics | expand

Commit Message

Storm, Christian June 2, 2023, 1:20 p.m. UTC
Fix General HTTP Server example type diagnostics.
Correctly make `channel` a field of the `suricatta` Table.
Factor out suricatta.channel.{put,get} return values.
Fix some @enum annotations that are actually @class.

Signed-off-by: Christian Storm <christian.storm@siemens.com>
---
 examples/suricatta/swupdate_suricatta.lua |  28 ++--
 suricatta/suricatta.lua                   | 189 ++++++++--------------
 2 files changed, 78 insertions(+), 139 deletions(-)
diff mbox series

Patch

diff --git a/examples/suricatta/swupdate_suricatta.lua b/examples/suricatta/swupdate_suricatta.lua
index dffc2909..a74905c9 100644
--- a/examples/suricatta/swupdate_suricatta.lua
+++ b/examples/suricatta/swupdate_suricatta.lua
@@ -84,9 +84,9 @@  end
 -- The default substitutions table is suitable for escaping
 -- to proper JSON.
 --
---- @param  str      string                The JSON string to be escaped
---- @param  substs?  table<string,string>  Substitutions to apply
---- @return string                         # The escaped JSON string
+--- @param  str      string  The JSON string to be escaped
+--- @param  substs?  table   Substitutions to apply
+--- @return string           # The escaped JSON string
 function escape(str, substs)
     local escapes = '[%z\1-\31"\\]'
     if not substs then
@@ -145,10 +145,10 @@  jobtype = {
 --- Configuration for the General Purpose HTTP Server.
 --
 --- @class gs
---- @field channel         table<string, channel>     Channels used in this module
---- @field channel_config  suricatta.channel.options  Channel options (defaults, shadowed by config file, shadowed by command line arguments)
---- @field job             job                        Current job information
---- @field polldelay       table                      Default and temporary delay between two server poll operations in seconds
+--- @field channel         table<string, suricatta.open_channel>  Channels used in this module
+--- @field channel_config  suricatta.channel.options              Channel options (defaults, shadowed by config file, shadowed by command line arguments)
+--- @field job             job                                    Current job information
+--- @field polldelay       table                                  Default and temporary delay between two server poll operations in seconds
 gs = {
     channel        = {},
     channel_config = {},
@@ -403,13 +403,14 @@  suricatta.server.register(install_update, suricatta.server.INSTALL_UPDATE)
 --
 -- Lua counterpart of `void server_print_help(void)`.
 --
---- @param  defaults  suricatta.channel.options  Compile-time channel default options ∪ { polldelay = CHANNEL_DEFAULT_POLLING_INTERVAL }
---- @return suricatta.status                     # Suricatta return code
+--- @param  defaults  suricatta.channel.options|table  Default options
+--- @return suricatta.status                           # Suricatta return code
 function print_help(defaults)
     defaults = defaults or {}
-    io.stdout:write(string.format("\t  -u <URL>          * URL to the server instance, e.g., http://localhost:8080\n"))
-    io.stdout:write(string.format("\t  -i <string>       * The device ID.\n"))
-    io.stdout:write(string.format("\t  -p <int>          Polling delay (default: %ds).\n", defaults.polldelay))
+    local stdout = io.output()
+    stdout:write(string.format("\t  -u <URL>          * URL to the server instance, e.g., http://localhost:8080\n"))
+    stdout:write(string.format("\t  -i <string>       * The device ID.\n"))
+    stdout:write(string.format("\t  -p <int>          Polling delay (default: %ds).\n", defaults.polldelay))
     return suricatta.status.OK
 end
 suricatta.server.register(print_help, suricatta.server.PRINT_HELP)
@@ -441,7 +442,8 @@  function server_start(defaults, argv, fconfig)
             gs.polldelay.default = tonumber(arg)
         elseif opt == ":" then
             io.stderr:write("Missing argument.")
-            print_help(defaults)
+            -- Note: .polldelay is in fconfig
+            print_help(setmetatable((defaults or {}), { __index = fconfig }))
             return suricatta.status.EINIT
         end
     end
diff --git a/suricatta/suricatta.lua b/suricatta/suricatta.lua
index 1fa32180..419b58c2 100644
--- a/suricatta/suricatta.lua
+++ b/suricatta/suricatta.lua
@@ -17,12 +17,18 @@ 
 -- luacheck: no max line length
 -- luacheck: no unused args
 
-local suricatta = {}
-
+-- Note: Definitions prefixed with `---` are not part of the SWUpdate functionality
+-- exposed to the Lua realm but instead are `typedef`-alikes returned by a function
+-- of the SWUpdate Suricatta Lua Module. Nonetheless, they are in the suricatta
+-- "namespace" for avoiding name clashes and, not least, convenience.
 
---- Lua equivalent of `server_op_res_t` enum as in `include/util.h`.
+--- SWUpdate Suricatta Binding.
 --
+--- @class suricatta
+local suricatta = {}
+
 --- @enum suricatta.status
+--- Lua equivalent of `server_op_res_t` enum as in `include/util.h`.
 suricatta.status = {
     OK                  = 0,
     EERR                = 1,
@@ -39,10 +45,10 @@  suricatta.status = {
 
 --- SWUpdate notify function bindings.
 --
--- Translates to `notify(string.format(message, ...))`, see
--- `corelib/lua_interface.c`.
+-- Translates to `notify(string.format(message, ...))`,
+-- @see `corelib/lua_interface.c`
 --
---- @type table<string, function>
+--- @class suricatta.notify
 suricatta.notify = {
     --- @type fun(message: string, ...: any)
     error    = function(message, ...) end,
@@ -63,15 +69,15 @@  suricatta.notify = {
 --
 --- @class suricatta.bootloader
 suricatta.bootloader = {
-    --- Bootloaders supported by SWUpdate.
-    --
     --- @enum suricatta.bootloader.bootloaders
+    --- Bootloaders supported by SWUpdate.
     bootloaders = {
         EBG   = "ebg",
         NONE  = "none",
         GRUB  = "grub",
         UBOOT = "uboot",
     },
+
     --- Operations on the currently set bootloader's environment.
     --
     --- @class suricatta.bootloader.env
@@ -117,7 +123,7 @@  suricatta.bootloader.env.apply = function(filename) end
 
 --- SWUpdate's persistent state IDs as in `include/state.h` and reverse-lookup.
 --
---- @enum suricatta.pstate
+--- @class suricatta.pstate
 suricatta.pstate = {
     OK            = string.byte('0'), [string.byte('0')] = "OK",
     INSTALLED     = string.byte('1'), [string.byte('1')] = "INSTALLED",
@@ -136,15 +142,15 @@  suricatta.pstate.get = function() end
 
 --- Save persistent state information.
 --
---- @param  state  suricatta.pstate  Persistent state ID number
---- @return boolean                  # Whether operation was successful or not
+--- @param  state  number  Persistent state ID number
+--- @return boolean | nil  # True on success, nil on error
 suricatta.pstate.save = function(state) end
 
 
 
 --- Function registry IDs for Lua suricatta functions.
 --
---- @enum suricatta.server
+--- @class suricatta.server
 suricatta.server = {
     HAS_PENDING_ACTION    = 0,
     INSTALL_UPDATE        = 1,
@@ -160,25 +166,46 @@  suricatta.server = {
 
 --- Register a Lua function as Suricatta interface implementation.
 --
---- @param  function_p  function          Function to register for `purpose`
---- @param  purpose     suricatta.server  Suricatta interface function implemented
---- @return boolean                       # Whether operation was successful or not
+--- @param  function_p  function   Function to register for `purpose`
+--- @param  purpose     number     Suricatta interface function implemented (one of suricatta.server's enums)
+--- @return boolean                # Whether operation was successful or not
 suricatta.server.register = function(function_p, purpose) end
 
 
+--- Channel result table.
+--
+-- Result in return of a channel operation.
+--
+--- @class suricatta.channel_operation_result
+--- @field http_response_code  number
+--- @field format              suricatta.channel.content
+--- @field json_reply          table | nil   Table if `format` was `suricatta.channel.content.JSON`
+--- @field raw_reply           string | nil  Table if `format` was `suricatta.channel.content.RAW`
+--- @field received_headers    table<string, string> | nil
+
+
+--- Options and methods on the opened channel.
+--
+-- Table as returned by `suricatta.channel.open()`.
+--
+--- @class suricatta.open_channel
+--- @field options  suricatta.channel.options                                                                               Channel creation-time set options as in `include/channel_curl.h`.
+--- @field get      fun(options: suricatta.channel.options): boolean, suricatta.status, suricatta.channel_operation_result  Channel get operation
+--- @field put      fun(options: suricatta.channel.options): boolean, suricatta.status, suricatta.channel_operation_result  Channel put operation
+--- @field close    fun()                                                                                                   Channel close operation
+
+--- @class suricatta.channel
 suricatta.channel = {
-    --- Content type passed over the channel as in `include/channel_curl.h`.
-    --
     --- @enum suricatta.channel.content
+    --- Content type passed over the channel as in `include/channel_curl.h`.
     content = {
         NONE = 0,
         JSON = 1,
         RAW  = 2,
     },
 
-    --- Transfer method to use over channel as in `include/channel_curl.h`.
-    --
     --- @enum suricatta.channel.method
+    --- Transfer method to use over channel as in `include/channel_curl.h`.
     method = {
         GET   = 0,
         POST  = 1,
@@ -216,118 +243,28 @@  suricatta.channel = {
     --- @field nofollow            boolean  `CURLOPT_FOLLOWLOCATION` - follow HTTP 3xx redirects
     --- @field max_download_speed  string   `CURLOPT_MAX_RECV_SPEED_LARGE` - rate limit data download speed
     --- @field headers_to_send     table<string, string>  Header to send
-    options = {
-        url                = "",
-        cached_file        = "",
-        auth               = "",
-        request_body       = "",
-        iface              = "",
-        dry_run            = false,
-        cafile             = "",
-        sslkey             = "",
-        sslcert            = "",
-        ciphers            = "",
-        proxy              = "",
-        info               = "",
-        auth_token         = "",
-        content_type       = "",
-        retry_sleep        = 5,
-        method             = 0,
-        retries            = 5,
-        low_speed_timeout  = 300,
-        connection_timeout = 300,
-        format             = 2,
-        debug              = false,
-        usessl             = false,
-        strictssl          = false,
-        nocheckanswer      = false,
-        nofollow           = true,
-        max_download_speed = "",
-        headers_to_send    = {},
-    },
+    options = {},
 
     --- Open a new channel.
     --
     --- @param  options  suricatta.channel.options  Channel default options overridable per operation
     --- @return boolean                             # Whether operation was successful or not
-    --- @return table                               # Options of and operations on the opened channel
-    open = function(options)
-        --- Returned channel instance, on successful open.
-        --
-        --- @type  table<string, any>
-        --- @class channel
-        --- @field options  suricatta.channel.options  Channel creation-time set options
-        --- @field get      function                   Channel get operation
-        --- @field put      function                   Channel put operation
-        --- @field close    function                   Channel close operation
-        return true, {
-
-            --- Channel creation-time set options as in `include/channel_curl.h`.
-            --
-            --- @type suricatta.channel.options
-            options = {},
-
-            --- Execute get operation over channel.
-            --
-            --- @param  options_get  suricatta.channel.options  Channel options for get operation
-            --- @return boolean           # Whether operation was successful or not
-            --- @return suricatta.status  # Suricatta return code
-            --- @return table             # Operation results
-            get = function(options_get)
-                return true, suricatta.status.OK, {
-                    --- @type number
-                    http_response_code = nil,
-                    --- @type suricatta.channel.content
-                    format             = nil,
-                    --- @type table | nil
-                    json_reply         = nil, -- if request method was `suricatta.channel.content.JSON`
-                    --- @type string | nil
-                    raw_reply          = nil, -- if request method was `suricatta.channel.content.RAW`
-                    --- @type table<string, string> | nil
-                    received_headers   = nil,
-                }
-            end,
-
-            --- Execute put operation over channel.
-            --
-            --- @param  options_put  suricatta.channel.options  Channel options for put operation
-            --- @return boolean           # Whether operation was successful or not
-            --- @return suricatta.status  # Suricatta return code
-            --- @return table             # Operation results
-            put = function(options_put)
-                return true, suricatta.status.OK, {
-                    --- @type number
-                    http_response_code = nil,
-                    --- @type suricatta.channel.content
-                    format             = nil,
-                    --- @type table | nil
-                    json_reply         = nil, -- if request method was `suricatta.channel.content.JSON`
-                    --- @type string | nil
-                    raw_reply          = nil, -- if request method was `suricatta.channel.content.RAW`
-                    --- @type table<string, string> | nil
-                    received_headers   = nil,
-                }
-            end,
-
-            --- Close channel.
-            close = function() end,
-        }
-    end,
+    --- @return suricatta.open_channel              # Options of and operations on the opened channel
+    open = function(options) end,
 }
 
 
---- @type  table<string, any>
---- @class suricatta.op_channel
+--- Channel and Options Table to use for an operation.
 --
 -- Channel to use for the download / installation operation as returned by `suricatta.channel.open()`
 -- plus channel options overriding the defaults per operation (@see suricatta.channel.options)
 -- and specific options to the download / installation operation, e.g., `drain_messages`.
 --
---- @field channel          channel                    Channel table as returned by `suricatta.channel.open()`
+--- @class suricatta.operation_channel
+--- @field channel          suricatta.open_channel     Channel table as returned by `suricatta.channel.open()`
 --- @field drain_messages?  boolean                    Whether to flush all progress messages or only those while in-flight operation (default)
 --- @field ∈?               suricatta.channel.options  Channel options to override for this operation
 
-
 --- Install an update artifact from remote server or local file.
 --
 -- If the protocol specified in Table `install_channel`'s `url` field is `file://`,
@@ -336,10 +273,10 @@  suricatta.channel = {
 -- Note that this file is to be deleted, if applicable, from the Lua realm.
 --
 --- @see suricatta.download
---- @param  install_channel  suricatta.op_channel  Channel to use for the download+installation operation
---- @return boolean                # Whether operation was successful or not
---- @return suricatta.status       # Suricatta return code
---- @return table<number, string>  # Error messages, if any
+--- @param  install_channel  suricatta.operation_channel  Channel to use for the download+installation operation
+--- @return boolean                                       # Whether operation was successful or not
+--- @return suricatta.status                              # Suricatta return code
+--- @return table<number, string>                         # Error messages, if any
 suricatta.install = function(install_channel) end
 
 --- Download an update artifact from remote server.
@@ -349,17 +286,17 @@  suricatta.install = function(install_channel) end
 -- an appropriate `install_channel` Table's `url` field.
 --
 --- @see suricatta.install
---- @param  download_channel  suricatta.op_channel  Channel to use for the download operation
---- @param  localpath         string                Path where to store the downloaded artifact to
---- @return boolean                # Whether operation was successful or not
---- @return suricatta.status       # Suricatta return code
---- @return table<number, string>  # Error messages, if any
+--- @param  download_channel  suricatta.operation_channel  Channel to use for the download operation
+--- @param  localpath         string                       Path where to store the downloaded artifact to
+--- @return boolean                                        # Whether operation was successful or not
+--- @return suricatta.status                               # Suricatta return code
+--- @return table<number, string>                          # Error messages, if any
 suricatta.download = function(download_channel, localpath) end
 
 
 --- Sleep for a number of seconds.
 --
--- Call SLEEP(3) via C realm.
+-- Call `SLEEP(3)` via C realm.
 --
 --- @param seconds number  # Number of seconds to sleep
 suricatta.sleep = function(seconds) end
@@ -382,7 +319,7 @@  suricatta.get_tmpdir = function() end
 
 --- Get SWUpdate version.
 --
---- @return suricatta.version  # Table with 'version' and 'patchlevel' fields
+--- @return suricatta.version  # Table with `version` and `patchlevel` fields
 suricatta.getversion = function() end