diff --git a/.gitattributes b/.gitattributes index 34028fc8..8a936709 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ docs.md linguist-documentation docs.md linguist-generated +meta.lua linguist-generated diff --git a/docgen.lua b/docgen.lua index 8a1a5a10..1f8efb92 100644 --- a/docgen.lua +++ b/docgen.lua @@ -1,10 +1,15 @@ -local doctypes = require('docs') -local doc = doctypes[1] -local types = doctypes[2] +--- This module is responsible for generating documentation and metadata for +--- the luv project. It processes documentation sections from docs.lua, +--- and writes the output to markdown (docs.md) and Lua files (meta.lua). + +local docs = require('docs') +local doctop = docs[1] +local types = docs[2] --- @param str string +--- @param indent? integer --- @return string -local function dedent(str) +local function dedent(str, indent) local prefix = 99 str = str:gsub('^\n', ''):gsub('%s+$', '') @@ -25,353 +30,844 @@ local function dedent(str) local ret = table.concat(result, '\n') ret = ret:gsub('\n+$', '') + if indent then + local ind = string.rep(' ', indent) + ret = ind .. ret:gsub('\n', '\n' .. ind) + ret = ret:gsub('\n%s+\n', '\n\n') + end + return ret end ---- @param lvl integer ---- @param str string ---- @return string -local function heading(lvl, str) - return string.rep('#', lvl) .. ' ' .. str:gsub(' %- ', ' — ') +--- Enumerates key-value pairs of a table, ordered by key. +--- @generic T: table, K, V +--- @param t T Dict-like table +--- @return fun(table: table, index?: K):K, V # |for-in| iterator over sorted keys and their values +--- @return T +local function spairs(t) + --- @cast t table + + -- collect the keys + local keys = {} + for k in pairs(t) do + table.insert(keys, k) + end + table.sort(keys) + + -- Return the iterator function. + local i = 0 + return function() + i = i + 1 + if keys[i] then + return keys[i], t[keys[i]] + end + end, + t +end + +--- @param ty Doc.Type +--- @return Doc.Type +local function remove_nil(ty) + if not (type(ty) == 'table' and ty.kind == 'union') then + return ty + end + local r = { kind = 'union', {} } --- @type Doc.Type.Union + for _, uty in ipairs(ty[1]) do + if uty ~= 'nil' then + table.insert(r[1], uty) + end + end + if #r[1] == 1 then + return r[1][1] + end + return r end +--- @type table +local gtypes = {} + +--- @param nm string --- @param ty Doc.Type ---- @return boolean -local function isoptional(ty) - if type(ty) == 'string' then - return ty == 'nil' +local function add_gtype(nm, ty) + if gtypes[ty] then + error('Type already exists: ' .. nm) + end + gtypes[ty] = nm + types[nm] = ty +end + +--- @param ns string +--- @param nm? string +--- @param ty Doc.Type +local function gen_type(ns, nm, ty) + ty = remove_nil(ty) + + if type(ty) ~= 'table' or gtypes[ty] then + return end - if ty.kind == 'union' then + + local ty_nm = nm and ('%s.%s'):format(ns, nm) or ns + + if ty.kind == 'function' then + if #ty.args > 2 then + add_gtype(ty_nm, ty) + end + for _, f in ipairs(ty.args) do + local arg_nm, arg_ty = f[1], f[2] + gen_type(ty_nm, arg_nm, arg_ty) + end + elseif ty.kind == 'union' then + local nonstrtys = 0 for _, uty in ipairs(ty[1]) do - if isoptional(uty) then - return true + if type(uty) == 'table' and not types[uty] then + nonstrtys = nonstrtys + 1 end end + + for i, uty in ipairs(ty[1]) do + gen_type(ty_nm, nonstrtys > 1 and '_' .. i or nil, uty) + end + elseif ty.kind == 'dict' then + gen_type(ty_nm, types[ty_nm] and 'value' or nil, ty.value) + elseif ty.kind == 'table' then + if #ty.fields > 2 or (#ty.fields > 0 and ty.fields[1][4]) then + add_gtype(ty_nm, ty) + end + for _, f in ipairs(ty.fields) do + local field_nm, field_ty = f[1], f[2] + gen_type(ty_nm, field_nm, field_ty) + end end - return false end ---- @param method Doc.Method ---- @return string -local function sig(method) - local args = {} --- @type string[] - for _, param in ipairs(method.params or {}) do - local nm = param.name - if isoptional(param.type) then - nm = '[' .. nm .. ']' +--- @param section Doc +local function gen_types_for_doc(section) + for _, funcs in ipairs(section.funcs or {}) do + for _, p in ipairs(funcs.params or {}) do + gen_type(funcs.name, p.name, p.type) + end + local returns = funcs.returns or funcs.returns_sync + if type(returns) == 'table' then + for _, p in ipairs(returns) do + gen_type(funcs.name, p[2], p[1]) + end end - args[#args + 1] = nm end - return ('`uv.%s(%s)`'):format(method.name, table.concat(args, ', ')) -end -local function pad(lvl) - return string.rep(' ', lvl * 2) + for _, subsection in ipairs(section.sections or {}) do + gen_types_for_doc(subsection) + end end -local normty +local Doc = {} ---- @param ty Doc.Type.Fun ---- @param lvl? integer ---- @param desc? string ---- @return string -local function normtyfun(ty, lvl, desc) - local r = {} --- @type string[] - r[#r + 1] = '`callable`' - if desc then - r[#r] = r[#r] .. ' ' .. desc +do -- doc + --- @param lvl integer + --- @param str string + --- @return string + local function heading(lvl, str) + return string.rep('#', lvl) .. ' ' .. str:gsub(' %- ', ' — ') end - for _, arg in ipairs(ty.args) do - local arg_nm, arg_ty, arg_desc = arg[1], arg[2], arg[3] - if arg_nm == 'err' then - arg_ty = 'nil|string' + + --- @param ty Doc.Type + --- @return boolean + local function isoptional(ty) + if type(ty) == 'string' then + return ty == 'nil' end - r[#r + 1] = ('%s- `%s`: %s'):format(pad(lvl), arg_nm, normty(arg_ty, lvl + 1)) - if arg_desc then - r[#r] = r[#r] .. ' ' .. arg_desc + if ty.kind == 'union' then + for _, uty in ipairs(ty[1]) do + if isoptional(uty) then + return true + end + end end + return false end - return table.concat(r, '\n') -end + local function pad(lvl) + return string.rep(' ', lvl * 2) + end ---- @param ty Doc.Type.Table ---- @param lvl? integer ---- @param desc? string ---- @return string -local function normtytbl(ty, lvl, desc) - local r = {} --- @type string[] - r[#r + 1] = '`table`' - if desc then - r[#r] = r[#r] .. ' ' .. desc + --- @param ty Doc.Type.Fun + --- @param lvl? integer + --- @param desc? string + --- @return string + local function tyfun(ty, lvl, desc) + local r = {} --- @type string[] + r[#r + 1] = '`callable`' + if desc then + r[#r] = r[#r] .. ' ' .. desc + end + for _, arg in ipairs(ty.args) do + local arg_nm, arg_ty, arg_desc = arg[1], arg[2], arg[3] + if arg_nm == 'err' then + arg_ty = 'nil|string' + end + r[#r + 1] = ('%s- `%s`: %s'):format(pad(lvl), arg_nm, Doc.ty(arg_ty, lvl + 1)) + if arg_desc then + r[#r] = r[#r] .. ' ' .. arg_desc + end + end + + return table.concat(r, '\n') end - for _, field in ipairs(ty.fields) do - local name, aty, default, adesc = field[1], field[2], field[3], field[4] - r[#r + 1] = ('%s- `%s`: %s'):format(pad(lvl), name, normty(aty, lvl + 1, adesc)) - if default then - r[#r] = ('%s (default: `%s`)'):format(r[#r], default) + + --- @param ty Doc.Type.Table + --- @param lvl? integer + --- @param desc? string + --- @return string + local function tytbl(ty, lvl, desc) + local r = {} --- @type string[] + r[#r + 1] = '`table`' + if desc then + r[#r] = r[#r] .. ' ' .. desc end + for _, field in ipairs(ty.fields) do + local name, aty, default, adesc = field[1], field[2], field[3], field[4] + r[#r + 1] = ('%s- `%s`: %s'):format(pad(lvl), name, Doc.ty(aty, lvl + 1, adesc)) + if default then + r[#r] = ('%s (default: `%s`)'):format(r[#r], default) + end + end + + return table.concat(r, '\n') end - return table.concat(r, '\n') -end + --- @param ty string + --- @param lvl? integer + --- @param desc? string + --- @return string + local function tystr(ty, lvl, desc) + do -- TODO(lewis6991): remove + if ty == 'uv_handle_t' or ty == 'uv_req_t' or ty == 'uv_stream_t' then + return '`userdata` for sub-type of `' .. ty .. '`' + end + ty = ty:gsub('uv_[a-z_]+', '%0 userdata') + ty = ty:gsub('%|', '` or `') + end ---- @param ty string ---- @param _lvl? integer ---- @param desc? string ---- @return string -local function normtystr(ty, _lvl, desc) - do -- TODO(lewis6991): remove - if ty == 'uv_handle_t' or ty == 'uv_req_t' or ty == 'uv_stream_t' then - return '`userdata` for sub-type of `' .. ty .. '`' + if desc then + if desc:match('\n') then + desc = '\n' .. dedent(desc, lvl * 2) + else + desc = ' ' .. desc + end + end + return '`' .. ty .. '`' .. (desc or '') + end + + --- @param ty Doc.Type.Dict + --- @param lvl? integer + --- @param desc? string + --- @return string + local function tydict(ty, lvl, desc) + local r = {} --- @type string[] + r[#r + 1] = '`table`' + if desc then + r[#r] = r[#r] .. ' ' .. desc + end + -- TODO(lewis6991): remove + if ty.key == 'integer' then + ty = { + kind = 'dict', + key = '1, 2, 3, ..., n', + value = ty.value, + } end - ty = ty:gsub('uv_[a-z_]+', '%0 userdata') - ty = ty:gsub('%|', '` or `') + r[#r + 1] = ('%s- `[%s]`: %s'):format(pad(lvl), ty.key, Doc.ty(ty.value, lvl + 1)) + return table.concat(r, '\n') end - local desc_str = desc and ' ' .. desc or '' - return '`' .. ty .. '`' .. desc_str -end + --- @param ty Doc.Type.Union + --- @param lvl? integer + --- @param desc? string + --- @return string + local function tyunion(ty, lvl, desc) + local tys = ty[1] ---- @param ty Doc.Type.Dict ---- @param lvl? integer ---- @param desc? string ---- @return string -local function normtydict(ty, lvl, desc) - local r = {} --- @type string[] - r[#r + 1] = '`table`' - if desc then - r[#r] = r[#r] .. ' ' .. desc - end - -- TODO(lewis6991): remove - if ty.key == 'integer' then - ty.key = '1, 2, 3, ..., n' - end - r[#r + 1] = ('%s- `[%s]`: %s'):format(pad(lvl), ty.key, normty(ty.value, lvl + 1)) - return table.concat(r, '\n') -end + local r = {} --- @type string[] ---- @param ty Doc.Type.Union ---- @param lvl? integer ---- @param desc? string ---- @return string -local function normtyunion(ty, lvl, desc) - local tys = ty[1] + local main_ty --- @type integer? + for i, uty in ipairs(tys) do + if Doc.ty(uty):match('\n') then + main_ty = i + end + r[#r + 1] = Doc.ty(uty, lvl, i == #tys and desc or nil) + end + + if main_ty and #tys > 1 then + local others = {} --- @type string[] + for i, oty in ipairs(r) do + if i ~= main_ty then + others[#others + 1] = oty + end + end + local other_ty_str = table.concat(others, ' or ') + -- local other_ty_str = table.concat(others, '|') - local r = {} --- @type string[] + return (r[main_ty]:gsub('\n', ' or ' .. other_ty_str .. '\n', 1)) + end - local main_ty --- @type integer? - for i, uty in ipairs(tys) do - if normty(uty):match('\n') then - main_ty = i + return table.concat(r, ' or ') + -- return table.concat(r, '|') + end + + local types_noinline = { + threadargs = true, + buffer = true, + } + + local ty_dispatch = { + ['function'] = tyfun, + ['table'] = tytbl, + ['dict'] = tydict, + ['union'] = tyunion, + } + + --- @param ty Doc.Type + --- @param lvl? integer + --- @param desc? string + --- @return string + function Doc.ty(ty, lvl, desc) + -- resolve type + if types[ty] and not types_noinline[ty] and not types[ty].extends then + ty = types[ty] + end + lvl = lvl or 0 + local f --- @type fun(ty: Doc.Type, lvl: integer, desc: string): string + if type(ty) == 'string' then + f = tystr + else + f = assert(ty_dispatch[ty.kind]) end - r[#r + 1] = normty(uty, lvl, i == #tys and desc or nil) + return f(ty, lvl, desc) + end + + --- @param out file* + --- @param param Doc.Func.Param + local function write_param(out, param) + out:write(('- `%s`:'):format(param.name)) + local ty = param.type + if ty then + out:write(' ', Doc.ty(ty, 1, param.desc)) + elseif param.desc then + out:write(' ', param.desc) + end + if param.default then + out:write((' (default: `%s`)'):format(param.default)) + end + out:write('\n') end - if main_ty and #tys > 1 then - local others = {} --- @type string[] - for i, oty in ipairs(r) do - if i ~= main_ty then - others[#others + 1] = oty + --- @param out file* + --- @param x string|Doc.Func.Return[] + --- @param variant? string + local function write_return(out, x, variant) + local variant_str = variant and (' (%s version)'):format(variant) or '' + if type(x) == 'string' then + out:write(('**Returns%s:** %s\n'):format(variant_str, Doc.ty(x))) + elseif type(x) == 'table' then + if x[2] and x[2][2] == 'err' and x[3] and x[3][2] == 'err_name' then + local sty = x[1][1] + sty = remove_nil(sty) + local rty = Doc.ty(sty, nil, 'or `fail`') + out:write(('**Returns%s:** %s\n\n'):format(variant_str, rty)) + return + else + local tys = {} --- @type string[] + for _, ret in ipairs(x) do + tys[#tys + 1] = Doc.ty(ret[1]) + end + out:write(('**Returns%s:** %s\n'):format(variant_str, table.concat(tys, ', '))) end + else + out:write('**Returns:** Nothing.\n') end - local other_ty_str = table.concat(others, ' or ') - -- local other_ty_str = table.concat(others, '|') + out:write('\n') + end - return (r[main_ty]:gsub('\n', ' or ' .. other_ty_str .. '\n', 1)) + --- @param out file* + --- @param x string + --- @param variant? string + local function write_return_doc(out, x, variant) + local variant_str = variant and (' (%s version)'):format(variant) or '' + out:write(('**Returns%s:**'):format(variant_str)) + local r = dedent(x) + out:write(r:sub(1, 1) == '-' and '\n' or ' ') + out:write(r, '\n\n') end - return table.concat(r, ' or ') - -- return table.concat(r, '|') -end + --- @param func Doc.Func + --- @return string + local function sig(func) + local args = {} --- @type string[] + for _, param in ipairs(func.params or {}) do + local nm = param.name + if isoptional(param.type) then + nm = '[' .. nm .. ']' + end + args[#args + 1] = nm + end + return ('`uv.%s(%s)`'):format(func.name, table.concat(args, ', ')) + end -local types_noinline = { - threadargs = true, - buffer = true, -} + --- @param out file* + --- @param func Doc.Func + --- @param lvl integer + local function write_func(out, func, lvl) + out:write(heading(lvl, sig(func)), '\n\n') ---- @param ty Doc.Type ---- @param lvl? integer ---- @param desc? string ---- @return string -function normty(ty, lvl, desc) - -- resolve type - if types[ty] and not types_noinline[ty] and not types[ty].extends then - ty = types[ty] - end - lvl = lvl or 0 - local f --- @type fun(ty: Doc.Type, lvl: integer, desc: string): string - if type(ty) == 'string' then - f = normtystr - elseif ty.kind == 'function' then - f = normtyfun - elseif ty.kind == 'table' then - f = normtytbl - elseif ty.kind == 'dict' then - f = normtydict - elseif ty.kind == 'union' then - f = normtyunion - end - return f(ty, lvl, desc) -end + if func.method_form then + out:write(('> method form `%s`\n\n'):format(func.method_form)) + end ---- @param out file* ---- @param param Doc.Method.Param -local function write_param(out, param) - out:write(('- `%s`:'):format(param.name)) - local ty = param.type - if ty then - out:write(' ', normty(ty, 1, param.desc)) - elseif param.desc then - out:write(' ', param.desc) - end - if param.default then - out:write((' (default: `%s`)'):format(param.default)) - end - out:write('\n') -end + if func.deprecated then + out:write('**Deprecated:** ', dedent(func.deprecated), '\n\n') + return + end ---- @param ty Doc.Type -local function remove_nil(ty) - if type(ty) == 'table' and ty.kind == 'union' then - for i, uty in ipairs(ty[1]) do - if uty == 'nil' then - table.remove(ty[1], i) - break + if func.params then + out:write('**Parameters:**\n') + for _, param in ipairs(func.params) do + write_param(out, param) + end + out:write('\n') + end + + if func.desc then + out:write(dedent(func.desc), '\n\n') + end + + if func.returns_doc then + write_return_doc(out, func.returns_doc) + elseif func.returns_sync and func.returns_async then + if func.returns_sync_doc then + write_return_doc(out, func.returns_sync_doc, 'sync') else - remove_nil(uty) + write_return(out, func.returns_sync, 'sync') end + write_return(out, func.returns_async, 'async') + else + write_return(out, func.returns) + end + + if func.example then + out:write(dedent(func.example), '\n\n') + end + + if func.see then + out:write(('See [%s][].\n\n'):format(func.see)) + end + + for _, note in ipairs(func.notes or {}) do + local notes = dedent(note) + out:write('**Note**:') + out:write(notes:sub(1, 3) == '1. ' and '\n' or ' ') + out:write(notes, '\n\n') + end + + for _, warn in ipairs(func.warnings or {}) do + out:write(('**Warning**: %s\n\n'):format(dedent(warn))) + end + + if func.since then + out:write(('**Note**: New in libuv version %s.\n\n'):format(func.since)) end end -end ---- @param out file* ---- @param x string|Doc.Method.Return[] ---- @param variant? string -local function write_return(out, x, variant) - local variant_str = variant and (' (%s version)'):format(variant) or '' - if type(x) == 'string' then - out:write(('**Returns%s:** %s\n'):format(variant_str, normty(x))) - elseif type(x) == 'table' then - if x[2] and x[2][2] == 'err' and x[3] and x[3][2] == 'err_name' then - local sty = x[1][1] - remove_nil(sty) - local rty = normty(sty, nil, 'or `fail`') - out:write(('**Returns%s:** %s\n\n'):format(variant_str, rty)) - return - else - local tys = {} --- @type string[] - for _, ret in ipairs(x) do - tys[#tys + 1] = normty(ret[1]) + --- @param out file* + --- @param doc Doc + --- @param lvl? integer + function Doc.write(out, doc, lvl) + lvl = lvl or 1 + local title = doc.title + if title then + out:write(heading(lvl, title)) + out:write('\n\n') + end + local id = doc.id + if id then + local tag = assert(title):match('^`[a-z_]+`') or title + out:write(('[%s]: #%s\n\n'):format(tag, id)) + end + + if doc.desc then + out:write(dedent(doc.desc), '\n\n') + end + + if doc.constants then + for _, constant in ipairs(doc.constants) do + out:write(('- `%s`: "%s"\n'):format(constant[1], constant[2])) end - out:write(('**Returns%s:** %s\n'):format(variant_str, table.concat(tys, ', '))) + out:write('\n') + end + + for _, alias in spairs(doc.aliases or {}) do + for _, a in ipairs(alias) do + out:write(('- `%s`: %s\n'):format(a[1], a[2])) + end + out:write('\n') + end + + for _, func in ipairs(doc.funcs or {}) do + write_func(out, func, lvl + 1) + end + + for _, subsection in ipairs(doc.sections or {}) do + Doc.write(out, subsection, lvl + 1) end - else - out:write('**Returns:** Nothing.\n') end - out:write('\n') end ---- @param out file* ---- @param method Doc.Method ---- @param lvl integer -local function write_method(out, method, lvl) - out:write(heading(lvl, sig(method)), '\n\n') +local Meta = {} - if method.method_form then - out:write(('> method form `%s`\n\n'):format(method.method_form)) +do -- meta + --- @param x string + --- @return string + local function id(x) + if x == 'repeat' then + x = 'repeat_' + end + return (x:gsub(' ', '_')) end - if method.deprecated then - out:write('**Deprecated:** ', dedent(method.deprecated), '\n\n') - return + --- @param func Doc.Func + --- @param method? {class: string, name: string} + --- @return string + local function sig(func, method) + local args = {} --- @type string[] + for i, param in ipairs(func.params or {}) do + if not (func.returns_async and param.name == 'callback') and (not method or i > 1) then + args[#args + 1] = id(param.name) + end + end + if method then + return ('function %s:%s(%s) end'):format(method.class, method.name, table.concat(args, ', ')) + end + return ('function uv.%s(%s) end'):format(func.name, table.concat(args, ', ')) end - if method.params then - out:write('**Parameters:**\n') - for _, param in ipairs(method.params) do - write_param(out, param) + --- @param ty Doc.Type + --- @param no_gtypes? boolean + --- @return string + function Meta.ty(ty, no_gtypes) + if type(ty) == 'string' then + if types[ty] then + ty = 'uv.' .. ty + end + return ty end - out:write('\n') - end - if method.desc then - out:write(dedent(method.desc), '\n\n') - end + if not no_gtypes and gtypes[ty] then + return 'uv.' .. gtypes[ty] + end - if method.returns_doc then - out:write('**Returns:**') - local r = dedent(method.returns_doc) - out:write(r:sub(1, 1) == '-' and '\n' or ' ') - out:write(r, '\n\n') - elseif method.returns_sync and method.returns_async then - write_return(out, method.returns_sync, 'sync') - write_return(out, method.returns_async, 'async') - else - write_return(out, method.returns) - end + if ty.kind == 'dict' then + return ('table<%s, %s>'):format(ty.key, Meta.ty(ty.value)) + elseif ty.kind == 'function' then + local r = {} --- @type string[] + for _, arg in pairs(ty.args) do + local arg_nm, arg_ty = arg[1], arg[2] + r[#r + 1] = ('%s: %s'):format(arg_nm, Meta.ty(arg_ty)) + end + return ('fun(%s)'):format(table.concat(r, ', ')) + elseif ty.kind == 'table' then + if #ty.fields == 0 then + return '{}' + end + local r = {} --- @type string[] + for _, arg in pairs(ty.fields) do + local field_nm, field_ty = arg[1], arg[2] + r[#r + 1] = ('%s: %s'):format(field_nm, Meta.ty(field_ty)) + end + return ('{ %s }'):format(table.concat(r, ', ')) + elseif ty.kind == 'union' then + local r = {} --- @type string[] + local add_optional = false + for i, uty in ipairs(ty[1]) do + if i == #ty[1] and uty == 'nil' then + add_optional = true + else + r[#r + 1] = Meta.ty(uty) + end + end + return table.concat(r, '|') .. (add_optional and '?' or '') + end - if method.example then - out:write(dedent(method.example), '\n\n') + error('unknown type: ' .. ty) end - if method.see then - out:write(('See [%s][].\n\n'):format(method.see)) + --- @param out file* + --- @param x string|Doc.Func.Return[]? + local function write_return(out, x) + if type(x) == 'string' then + out:write('--- @return ', Meta.ty(x), '\n') + elseif type(x) == 'table' then + for _, ret in ipairs(x) do + out:write('--- @return ', Meta.ty(ret[1])) + if ret[2] then + out:write(' ', id(ret[2])) + end + out:write('\n') + end + end end - for _, note in ipairs(method.notes or {}) do - local notes = dedent(note) - out:write('**Note**:') - out:write(notes:sub(1, 3) == '1. ' and '\n' or ' ') - out:write(notes, '\n\n') - end + --- @param out file* + --- @param func Doc.Func + --- @param x string|Doc.Func.Return[] + local function write_async_overload(out, func, x) + if type(x) == 'string' then + x = { { x } } + end - for _, warn in ipairs(method.warnings or {}) do - out:write(('**Warning**: %s\n\n'):format(dedent(warn))) - end + out:write('--- @overload fun(') + local args = {} --- @type string[] + for _, arg in ipairs(func.params) do + local ty = arg.type + if arg.name == 'callback' then + ty = remove_nil(ty) + end + args[#args + 1] = ('%s: %s'):format(id(arg.name), Meta.ty(ty)) + end + out:write(table.concat(args, ', '), '): ') - if method.since then - out:write(('**Note**: New in libuv version %s.\n\n'):format(method.since)) + local ret = {} --- @type string[] + for _, r in ipairs(x) do + ret[#ret + 1] = Meta.ty(r[1]) + end + out:write(table.concat(ret, ', '), '\n') + end + + --- @param out file* + --- @param str string + local function write_comment(out, str) + --- @diagnostic disable-next-line: no-unknown + for line, nl in str:gmatch('([^\r\n]*)([\n\r]?)') do + if line ~= '' then + out:write('--- ', line, '\n') + elseif nl ~= '' then + out:write('---\n') + end + end end -end ---- @param out file* ---- @param section Doc ---- @param lvl integer -local function write_section(out, section, lvl) - local title = section.title - if title then - out:write(heading(lvl, title)) - out:write('\n\n') - end - local id = section.id - if id then - local tag = assert(title):match('^`[a-z_]+`') or title - out:write(('[%s]: #%s\n\n'):format(tag, id)) + local types_written = {} --- @type table + + --- @param out file* + --- @param nm string + --- @param ty Doc.Type + --- @param nonl? boolean + --- @return boolean + local function write_type(out, nm, ty, nonl) + if types_written[nm] then + return false + end + types_written[nm] = true + + if type(ty) == 'string' then + out:write('--- @alias ', Meta.ty(nm), ' ', Meta.ty(ty), '\n\n') + end + + if ty.kind == 'dict' then + if type(ty.value) == 'string' then + out:write( + '--- @alias ', + Meta.ty(nm), + ' table<', + Meta.ty(ty.key), + ',', + Meta.ty(ty.value), + '>\n' + ) + else + out:write('--- @class ', Meta.ty(nm), '\n') + out:write('--- @field [', Meta.ty(ty.key), '] ', Meta.ty(ty.value), '\n') + end + elseif ty.kind == 'table' then + out:write('--- @class ', Meta.ty(nm)) + if ty.extends then + out:write(' : ', Meta.ty(ty.extends)) + end + out:write('\n') + for _, arg in pairs(ty.fields) do + local name, aty, desc = arg[1], arg[2], arg[4] + if desc then + out:write('---\n') + write_comment(out, dedent(desc)) + end + out:write('--- @field ', name, ' ', Meta.ty(aty), '\n') + end + elseif ty.kind == 'union' then + local tys = ty[1] + out:write('--- @alias ', Meta.ty(nm), '\n') + for _, uty in ipairs(tys) do + out:write('--- | ', Meta.ty(uty), '\n') + end + elseif ty.kind == 'function' then + out:write('--- @alias ', Meta.ty(nm), '\n') + out:write('--- | ', Meta.ty(ty, true), '\n') + else + error('unknown') + end + if not nonl then + out:write('\n') + end + + return true end - if section.desc then - out:write(dedent(section.desc), '\n\n') + --- @param out file* + --- @param func Doc.Func + --- @param method? { class: string, name: string } + local function write_func(out, func, method) + for nm, ty in spairs(types) do + if nm:sub(1, #func.name) == func.name then + write_type(out, nm, ty) + end + end + + if func.deprecated then + out:write('--- @deprecated ', dedent(func.deprecated), '\n') + end + + if func.desc then + write_comment(out, dedent(func.desc)) + end + + if func.example then + out:write('--- Example\n') + write_comment(out, dedent(func.example)) + end + + for _, note in ipairs(func.notes or {}) do + local notes = dedent(note) + out:write('--- **Note**:\n') + write_comment(out, notes) + end + + for _, warn in ipairs(func.warnings or {}) do + out:write('--- **Warning**:\n') + write_comment(out, dedent(warn)) + end + + -- if method.see then + -- out:write(('--- @see %s\n'):format(method.see)) + -- end + + -- if method.since then + -- out:write(('**Note**: New in libuv version %s.\n\n'):format(method.since)) + -- end + + if func.params then + for i, param in ipairs(func.params) do + if not (func.returns_async and param.name == 'callback') and (not method or i > 1) then + out:write('--- @param ', id(param.name), ' ', Meta.ty(param.type)) + if param.desc then + if param.desc:match('\n') then + write_comment(out, param.desc) + else + out:write(' ', param.desc) + end + end + out:write('\n') + end + end + end + + write_return(out, func.returns or func.returns_sync) + if func.returns_async then + write_async_overload(out, func, func.returns_async) + end + + out:write(sig(func, method), '\n\n') end - if section.constants then - for _, constant in ipairs(section.constants) do - out:write(('- `%s`: "%s"\n'):format(constant[1], constant[2])) + --- @param out file* + --- @param doc Doc + local function write_doc(out, doc) + if doc.title then + out:write('--- # ', doc.title, '\n') + end + + if doc.desc then + if doc.title then + out:write('---\n') + end + write_comment(out, dedent(doc.desc)) + end + + if doc.class then + assert(write_type(out, doc.class, types[doc.class], true)) + out:write('local ', doc.class, ' = {}\n') + end + + for _, constant in ipairs(doc.constants or {}) do + out:write(("uv.constants.%s = '%s'\n"):format(constant[1], constant[2])) end + + for name, alias in spairs(doc.aliases or {}) do + out:write('\n') + out:write(('--- @alias uv.%s\n'):format(name)) + for _, a in ipairs(alias) do + out:write(("--- | '%s' # %s\n"):format(a[1], a[2])) + end + end + + if doc.funcs then + out:write('\n') + for _, func in ipairs(doc.funcs or {}) do + write_func(out, func) + if func.method_form then + assert(func.params, func.name) + local name = func.method_form:match('^[%w_]+%:([%w_]+)%(') + local class = func.params[1].type + assert(type(class) == 'string') + if write_type(out, class, types[class], true) then + out:write('local ', class, ' = {}\n\n') + end + write_func(out, func, { class = class, name = name }) + end + end + end + + if doc.sections then + out:write('\n') + for _, subsection in ipairs(doc.sections) do + write_doc(out, subsection) + end + end + out:write('\n') end - for _, method in ipairs(section.methods or {}) do - write_method(out, method, lvl + 1) - end + --- @param out file* + --- @param doc Doc + function Meta.write(out, doc) + out:write('--- @meta\n') + out:write('--- @class uv\n') + out:write('local uv = {}\n') + out:write('uv.constants = {}\n') + out:write('\n') - for _, subsection in ipairs(section.sections or {}) do - write_section(out, subsection, lvl + 1) + write_doc(out, doc) + + for nm, ty in spairs(types) do + write_type(out, nm, ty) + end end end -local out = assert(io.open('docs.md', 'w')) +local function main() + -- Generate types for large inline types + gen_types_for_doc(doctop) + + local outdoc = assert(io.open('docs.md', 'w')) + Doc.write(outdoc, doctop) -for _, section in ipairs(doc) do - write_section(out, section, 1) + local outmeta = assert(io.open('meta.lua', 'w')) + Meta.write(outmeta, doctop) end + +main() diff --git a/docs.lua b/docs.lua index f9801ffe..de4116c9 100644 --- a/docs.lua +++ b/docs.lua @@ -34,24 +34,25 @@ --- | Doc.Type.Dict --- | Doc.Type.Union ---- @class (exact) Doc.Method.Param +--- @class (exact) Doc.Func.Param --- @field name string ---- @field type? Doc.Type +--- @field type Doc.Type --- @field desc? string --- @field default? string ---- @alias Doc.Method.Return [Doc.Type, string] +--- @alias Doc.Func.Return [Doc.Type, string] ---- @class (exact) Doc.Method +--- @class (exact) Doc.Func --- @field name string --- @field desc? string --- @field deprecated? string --- @field since? string ---- @field params? Doc.Method.Param[] ---- @field returns? string|Doc.Method.Return[] ---- @field returns_sync? string|Doc.Method.Return[] ---- @field returns_async? string|Doc.Method.Return[] +--- @field params? Doc.Func.Param[] +--- @field returns? string|Doc.Func.Return[] +--- @field returns_sync? string|Doc.Func.Return[] +--- @field returns_async? string|Doc.Func.Return[] --- @field returns_doc? string +--- @field returns_sync_doc? string --- @field notes? string[] --- @field warnings? string[] --- @field example? string @@ -62,9 +63,11 @@ --- @field title? string --- @field desc? string --- @field id? string +--- @field class? string --- @field sections? Doc[] ---- @field methods? Doc.Method[] ---- @field constants? [string,string][]> +--- @field funcs? Doc.Func[] +--- @field constants? [string,string][] +--- @field aliases? table --- @param ... Doc.Type --- @return Doc.Type.Union @@ -82,6 +85,10 @@ local function opt(ty) return union(ty, 'nil') end +local opt_str = opt('string') +local opt_int = opt('integer') +local opt_bool = opt('boolean') + --- @param t? Doc.Type.Table.Attrs --- @return Doc.Type.Table local function table(t) @@ -118,8 +125,8 @@ end local function ret_or_fail(ty, name) return { { opt(ty), name }, - { opt('string'), 'err' }, - { opt('string'), 'err_name' }, + { opt_str, 'err' }, + { opt('uv.error_name'), 'err_name' }, } end @@ -135,7 +142,7 @@ end --- @param args? [string, Doc.Type, string?][] --- @param optional? boolean --- @param desc? string ---- @return Doc.Method.Param +--- @return Doc.Func.Param local function cb(args, optional, desc) --- @type Doc.Type local ty = fun(args or {}) @@ -152,23 +159,106 @@ end --- @param args? [string, Doc.Type, string?][] --- @param optional? boolean --- @param desc? string ---- @return Doc.Method.Param +--- @return Doc.Func.Param local function cb_err(args, optional, desc) return cb({ - { 'err', opt('string') }, + { 'err', opt_str }, unpack(args or {}), }, optional, desc) end --- @param args? [string, Doc.Type, string?][] ---- @return Doc.Method.Param +--- @return Doc.Func.Param local function async_cb(args) - args = args or { { 'success', opt('boolean') } } + args = args or { { 'success', opt_bool } } return cb_err(args, true, '(async if provided, sync if `nil`)') end local success_ret = ret_or_fail('0', 'success') +local error_names = { + { 'E2BIG', 'argument list too long.' }, + { 'EACCES', 'permission denied.' }, + { 'EADDRINUSE', 'address already in use.' }, + { 'EADDRNOTAVAIL', 'address not available.' }, + { 'EAFNOSUPPORT', 'address family not supported.' }, + { 'EAGAIN', 'resource temporarily unavailable.' }, + { 'EAI_ADDRFAMILY', 'address family not supported.' }, + { 'EAI_AGAIN', 'temporary failure.' }, + { 'EAI_BADFLAGS', 'bad ai_flags value.' }, + { 'EAI_BADHINTS', 'invalid value for hints.' }, + { 'EAI_CANCELED', 'request canceled.' }, + { 'EAI_FAIL', 'permanent failure.' }, + { 'EAI_FAMILY', 'ai_family not supported.' }, + { 'EAI_MEMORY', 'out of memory.' }, + { 'EAI_NODATA', 'no address.' }, + { 'EAI_NONAME', 'unknown node or service.' }, + { 'EAI_OVERFLOW', 'argument buffer overflow.' }, + { 'EAI_PROTOCOL', 'resolved protocol is unknown.' }, + { 'EAI_SERVICE', 'service not available for socket type.' }, + { 'EAI_SOCKTYPE', 'socket type not supported.' }, + { 'EALREADY', 'connection already in progress.' }, + { 'EBADF', 'bad file descriptor.' }, + { 'EBUSY', 'resource busy or locked.' }, + { 'ECANCELED', 'operation canceled.' }, + { 'ECHARSET', 'invalid Unicode character.' }, + { 'ECONNABORTED', 'software caused connection abort.' }, + { 'ECONNREFUSED', 'connection refused.' }, + { 'ECONNRESET', 'connection reset by peer.' }, + { 'EDESTADDRREQ', 'destination address required.' }, + { 'EEXIST', 'file already exists.' }, + { 'EFAULT', 'bad address in system call argument.' }, + { 'EFBIG', 'file too large.' }, + { 'EHOSTUNREACH', 'host is unreachable.' }, + { 'EINTR', 'interrupted system call.' }, + { 'EINVAL', 'invalid argument.' }, + { 'EIO', 'i/o error.' }, + { 'EISCONN', 'socket is already connected.' }, + { 'EISDIR', 'illegal operation on a directory.' }, + { 'ELOOP', 'too many symbolic links encountered.' }, + { 'EMFILE', 'too many open files.' }, + { 'EMSGSIZE', 'message too long.' }, + { 'ENAMETOOLONG', 'name too long.' }, + { 'ENETDOWN', 'network is down.' }, + { 'ENETUNREACH', 'network is unreachable.' }, + { 'ENFILE', 'file table overflow.' }, + { 'ENOBUFS', 'no buffer space available.' }, + { 'ENODEV', 'no such device.' }, + { 'ENOENT', 'no such file or directory.' }, + { 'ENOMEM', 'not enough memory.' }, + { 'ENONET', 'machine is not on the network.' }, + { 'ENOPROTOOPT', 'protocol not available.' }, + { 'ENOSPC', 'no space left on device.' }, + { 'ENOSYS', 'function not implemented.' }, + { 'ENOTCONN', 'socket is not connected.' }, + { 'ENOTDIR', 'not a directory.' }, + { 'ENOTEMPTY', 'directory not empty.' }, + { 'ENOTSOCK', 'socket operation on non-socket.' }, + { 'ENOTSUP', 'operation not supported on socket.' }, + { 'EOVERFLOW', 'value too large for defined data type.' }, + { 'EPERM', 'operation not permitted.' }, + { 'EPIPE', 'broken pipe.' }, + { 'EPROTO', 'protocol error.' }, + { 'EPROTONOSUPPORT', 'protocol not supported.' }, + { 'EPROTOTYPE', 'protocol wrong type for socket.' }, + { 'ERANGE', 'result too large.' }, + { 'EROFS', 'read-only file system.' }, + { 'ESHUTDOWN', 'cannot send after transport endpoint shutdown.' }, + { 'ESPIPE', 'invalid seek.' }, + { 'ESRCH', 'no such process.' }, + { 'ETIMEDOUT', 'connection timed out.' }, + { 'ETXTBSY', 'text file is busy.' }, + { 'EXDEV', 'cross-device link not permitted.' }, + { 'UNKNOWN', 'unknown error.' }, + { 'EOF', 'end of file.' }, + { 'ENXIO', 'no such device or address.' }, + { 'EMLINK', 'too many links.' }, + { 'ENOTTY', 'inappropriate ioctl for device.' }, + { 'EFTYPE', 'inappropriate file type or format.' }, + { 'EILSEQ', 'illegal byte sequence.' }, + { 'ESOCKTNOSUPPORT', 'socket type not supported.' }, +} + --- @type table local constants = { address_families = { @@ -275,42 +365,26 @@ local types = { buffer = union('string', 'string[]'), - ['getaddrinfo.hints'] = table({ - { 'family', opt(union('string', 'integer')) }, - { 'socktype', opt(union('string', 'integer')) }, - { 'protocol', opt(union('string', 'integer')) }, - { 'addrconfig', opt('boolean') }, - { 'v4mapped', opt('boolean') }, - { 'all', opt('boolean') }, - { 'numerichost', opt('boolean') }, - { 'passive', opt('boolean') }, - { 'numericserv', opt('boolean') }, - { 'canonname', opt('boolean') }, + address = table({ + { 'addr', 'string' }, + { 'family', 'string' }, + { 'port', opt_int }, + { 'socktype', 'string' }, + { 'protocol', 'string' }, + { 'canonname', opt_str }, }), - addresses = dict( - 'integer', - table({ - { 'addr', 'string' }, - { 'family', 'string' }, - { 'port', opt('integer') }, - { 'socktype', 'string' }, - { 'protocol', 'string' }, - { 'canonname', opt('string') }, - }) - ), socketinfo = table({ { 'ip', 'string' }, { 'family', 'string' }, { 'port', 'integer' }, }), - ['socket.type'] = union("'stream'", "'dgram'", "'raw'", "'rdm'", "'seqpacket'"), - ['fs_stat.result.time'] = table({ { 'sec', 'integer' }, { 'nsec', 'integer' }, }), + ['fs_stat.result'] = table({ { 'dev', 'integer' }, { 'mode', 'integer' }, @@ -330,6 +404,7 @@ local types = { { 'birthtime', 'fs_stat.result.time' }, { 'type', 'string' }, }), + ['fs_statfs.result'] = table({ { 'type', 'integer' }, { 'bsize', 'integer' }, @@ -339,10 +414,12 @@ local types = { { 'files', 'integer' }, { 'ffree', 'integer' }, }), + ['getrusage.result.time'] = table({ { 'sec', 'integer' }, { 'usec', 'integer' }, }), + ['getrusage.result'] = table({ { 'utime', 'getrusage.result.time', nil, '(user CPU time used)' }, { 'stime', 'getrusage.result.time', nil, '(system CPU time used)' }, @@ -363,4243 +440,4291 @@ local types = { }), } ---- @type Doc[] +--- @type Doc local doc = { - { - title = 'LibUV in Lua', - desc = [[ - The [luv][] project provides access to the multi-platform support library - [libuv][] in Lua code. It was primarily developed for the [luvit][] project as - the built-in `uv` module, but can be used in other Lua environments. - - More information about the core libuv library can be found at the original - [libuv documentation page][]. - ]], - sections = { - { -- lvl 3 sections - sections = { - { - title = 'TCP Echo Server Example', - desc = [[ - Here is a small example showing a TCP echo server: - - ```lua - local uv = require("luv") -- "luv" when stand-alone, "uv" in luvi apps - - local server = uv.new_tcp() - server:bind("127.0.0.1", 1337) - server:listen(128, function (err) + title = 'LibUV in Lua', + desc = [[ + The [luv][] project provides access to the multi-platform support library + [libuv][] in Lua code. It was primarily developed for the [luvit][] project as + the built-in `uv` module, but can be used in other Lua environments. + + More information about the core libuv library can be found at the original + [libuv documentation page][]. + ]], + sections = { + { -- lvl 3 sections + sections = { + { + title = 'TCP Echo Server Example', + desc = [[ + Here is a small example showing a TCP echo server: + + ```lua + local uv = require("luv") -- "luv" when stand-alone, "uv" in luvi apps + + local server = uv.new_tcp() + server:bind("127.0.0.1", 1337) + server:listen(128, function (err) + assert(not err, err) + local client = uv.new_tcp() + server:accept(client) + client:read_start(function (err, chunk) assert(not err, err) - local client = uv.new_tcp() - server:accept(client) - client:read_start(function (err, chunk) - assert(not err, err) - if chunk then - client:write(chunk) - else - client:shutdown() - client:close() - end - end) + if chunk then + client:write(chunk) + else + client:shutdown() + client:close() + end end) - print("TCP server listening at 127.0.0.1 port 1337") - uv.run() -- an explicit run call is necessary outside of luvit - ``` + end) + print("TCP server listening at 127.0.0.1 port 1337") + uv.run() -- an explicit run call is necessary outside of luvit + ``` + ]], + }, + { + title = 'Module Layout', + desc = [[ + The luv library contains a single Lua module referred to hereafter as `uv` for + simplicity. This module consists mostly of functions with names corresponding to + their original libuv versions. For example, the libuv function `uv_tcp_bind` has + a luv version at `uv.tcp_bind`. Currently, only two non-function fields exists: + `uv.constants` and `uv.errno`, which are tables. + ]], + }, + { + title = 'Functions vs Methods', + desc = [[ + In addition to having simple functions, luv provides an optional method-style + API. For example, `uv.tcp_bind(server, host, port)` can alternatively be called + as `server:bind(host, port)`. Note that the first argument `server` becomes the + object and `tcp_` is removed from the function name. Method forms are + documented below where they exist. + ]], + }, + { + title = 'Synchronous vs Asynchronous Functions', + desc = [[ + Functions that accept a callback are asynchronous. These functions may + immediately return results to the caller to indicate their initial status, but + their final execution is deferred until at least the next libuv loop iteration. + After completion, their callbacks are executed with any results passed to it. + + Functions that do not accept a callback are synchronous. These functions + immediately return their results to the caller. + + Some (generally FS and DNS) functions can behave either synchronously or + asynchronously. If a callback is provided to these functions, they behave + asynchronously; if no callback is provided, they behave synchronously. + ]], + }, + { + title = 'Pseudo-Types', + desc = [[ + Some unique types are defined. These are not actual types in Lua, but they are + used here to facilitate documenting consistent behavior: + - `fail`: an assertable `nil, string, string` tuple (see [Error Handling][]) + - `callable`: a `function`; or a `table` or `userdata` with a `__call` + metamethod + - `buffer`: a `string` or a sequential `table` of `string`s + - `threadargs`: variable arguments (`...`) of type `nil`, `boolean`, `number`, + `string`, or `userdata`, numbers of argument limited to 9. + ]], + }, + }, + }, + { + title = 'Contents', + desc = [[ + This documentation is mostly a retelling of the [libuv API documentation][] + within the context of luv's Lua API. Low-level implementation details and + unexposed C functions and types are not documented here except for when they + are relevant to behavior seen in the Lua module. + + - [Constants][] + - [Error Handling][] + - [Version Checking][] + - [`uv_loop_t`][] — Event loop + - [`uv_req_t`][] — Base request + - [`uv_handle_t`][] — Base handle + - [`uv_timer_t`][] — Timer handle + - [`uv_prepare_t`][] — Prepare handle + - [`uv_check_t`][] — Check handle + - [`uv_idle_t`][] — Idle handle + - [`uv_async_t`][] — Async handle + - [`uv_poll_t`][] — Poll handle + - [`uv_signal_t`][] — Signal handle + - [`uv_process_t`][] — Process handle + - [`uv_stream_t`][] — Stream handle + - [`uv_tcp_t`][] — TCP handle + - [`uv_pipe_t`][] — Pipe handle + - [`uv_tty_t`][] — TTY handle + - [`uv_udp_t`][] — UDP handle + - [`uv_fs_event_t`][] — FS Event handle + - [`uv_fs_poll_t`][] — FS Poll handle + - [File system operations][] + - [Thread pool work scheduling][] + - [DNS utility functions][] + - [Threading and synchronization utilities][] + - [Miscellaneous utilities][] + - [Metrics operations][] + ]], + }, + { + title = 'Constants', + id = 'constants', + desc = [[ + As a Lua library, luv supports and encourages the use of lowercase strings to + represent options. For example: + ```lua + -- signal start with string input + uv.signal_start("sigterm", function(signame) + print(signame) -- string output: "sigterm" + end) + ``` + + However, luv also superficially exposes libuv constants in a Lua table at + `uv.constants` where its keys are uppercase constant names and their associated + values are integers defined internally by libuv. The values from this table may + be supported as function arguments, but their use may not change the output + type. For example: + + ```lua + -- signal start with integer input + uv.signal_start(uv.constants.SIGTERM, function(signame) + print(signame) -- string output: "sigterm" + end) + ``` + + The uppercase constants defined in `uv.constants` that have associated + lowercase option strings are listed below. + ]], + sections = { + { + title = 'Address Families', + constants = constants.address_families, + }, + { + title = 'Signals', + constants = constants.signals, + }, + { + title = 'Socket Types', + constants = constants.socket_types, + }, + { + title = 'TTY Modes', + constants = constants.tty_modes, + }, + }, + }, + { + title = 'Error Handling', + id = 'error-handling', + desc = [[ + In libuv, errors are represented by negative numbered constants. While these + constants are made available in the `uv.errno` table, they are not returned by + luv functions and the libuv functions used to handle them are not exposed. + Instead, if an internal error is encountered, the failing luv function will + return to the caller an assertable `nil, err, name` tuple: + + - `nil` idiomatically indicates failure + - `err` is a string with the format `{name}: {message}` + - `{name}` is the error name provided internally by `uv_err_name` + - `{message}` is a human-readable message provided internally by `uv_strerror` + - `name` is the same string used to construct `err` + + This tuple is referred to below as the `fail` pseudo-type. + + When a function is called successfully, it will return either a value that is + relevant to the operation of the function, or the integer `0` to indicate + success, or sometimes nothing at all. These cases are documented below. + + Below is a list of known error names and error strings. See libuv's + [error constants][] page for an original source. + ]], + aliases = { error_name = error_names }, + }, + { + title = 'Version Checking', + id = 'version-checking', + funcs = { + { + name = 'version', + desc = [[ + Returns the libuv version packed into a single integer. 8 bits are used for each + component, with the patch number stored in the 8 least significant bits. For + example, this would be 0x010203 in libuv 1.2.3. + ]], + returns = 'integer', + }, + { + name = 'version_string', + desc = [[ + Returns the libuv version number as a string. For example, this would be "1.2.3" + in libuv 1.2.3. For non-release versions, the version suffix is included. + ]], + returns = 'string', + }, + }, + }, + { + title = '`uv_loop_t` - Event loop', + id = 'uv_loop_t--event-loop', + desc = [[ + The event loop is the central part of libuv's functionality. It takes care of + polling for I/O and scheduling callbacks to be run based on different sources of + events. + + In luv, there is an implicit uv loop for every Lua state that loads the library. + You can use this library in an multi-threaded environment as long as each thread + has it's own Lua state with its corresponding own uv loop. This loop is not + directly exposed to users in the Lua module. + ]], + funcs = { + { + name = 'loop_close', + desc = [[ + Closes all internal loop resources. In normal execution, the loop will + automatically be closed when it is garbage collected by Lua, so it is not + necessary to explicitly call `loop_close()`. Call this function only after the + loop has finished executing and all open handles and requests have been closed, + or it will return `EBUSY`. + ]], + returns = success_ret, + }, + { + name = 'run', + desc = [[ + This function runs the event loop. It will act differently depending on the + specified mode: + + - `"default"`: Runs the event loop until there are no more active and + referenced handles or requests. Returns `true` if `uv.stop()` was called and + there are still active handles or requests. Returns `false` in all other + cases. + + - `"once"`: Poll for I/O once. Note that this function blocks if there are no + pending callbacks. Returns `false` when done (no active handles or requests + left), or `true` if more callbacks are expected (meaning you should run the + event loop again sometime in the future). + + - `"nowait"`: Poll for I/O once but don't block if there are no pending + callbacks. Returns `false` if done (no active handles or requests left), + or `true` if more callbacks are expected (meaning you should run the event + loop again sometime in the future). + + ]], + notes = { + [[ + Luvit will implicitly call `uv.run()` after loading user code, but if + you use the luv bindings directly, you need to call this after registering + your initial set of event callbacks to start the event loop. ]], }, - { - title = 'Module Layout', - desc = [[ - The luv library contains a single Lua module referred to hereafter as `uv` for - simplicity. This module consists mostly of functions with names corresponding to - their original libuv versions. For example, the libuv function `uv_tcp_bind` has - a luv version at `uv.tcp_bind`. Currently, only two non-function fields exists: - `uv.constants` and `uv.errno`, which are tables. + params = { + { name = 'mode', type = opt_str, default = '"default"' }, + }, + -- If loop is already running then returns (nil, string) + returns = ret_or_fail('boolean', 'running'), + }, + { + name = 'loop_configure', + desc = [[ + Set additional loop options. You should normally call this before the first call + to uv_run() unless mentioned otherwise. + + Supported options: + + - `"block_signal"`: Block a signal when polling for new events. The second argument + to loop_configure() is the signal name (as a lowercase string) or the signal number. + This operation is currently only implemented for `"sigprof"` signals, to suppress + unnecessary wakeups when using a sampling profiler. Requesting other signals will + fail with `EINVAL`. + - `"metrics_idle_time"`: Accumulate the amount of idle time the event loop spends + in the event provider. This option is necessary to use `metrics_idle_time()`. + + An example of a valid call to this function is: + + ```lua + uv.loop_configure("block_signal", "sigprof") + ``` + ]], + notes = { + [[ + Be prepared to handle the `ENOSYS` error; it means the loop option is + not supported by the platform. ]], }, - { - title = 'Functions vs Methods', - desc = [[ - In addition to having simple functions, luv provides an optional method-style - API. For example, `uv.tcp_bind(server, host, port)` can alternatively be called - as `server:bind(host, port)`. Note that the first argument `server` becomes the - object and `tcp_` is removed from the function name. Method forms are - documented below where they exist. + params = { + { name = 'option', type = 'string' }, + { name = '...', type = 'any', desc = 'depends on `option`' }, + }, + returns = success_ret, + }, + { + name = 'loop_mode', + desc = [[ + If the loop is running, returns a string indicating the mode in use. If the loop + is not running, `nil` is returned instead. + ]], + returns = { { opt_str } }, + }, + { + name = 'loop_alive', + desc = [[ + Returns `true` if there are referenced active handles, active requests, or + closing handles in the loop; otherwise, `false`. + ]], + returns = ret_or_fail('boolean', 'alive'), + }, + { + name = 'stop', + desc = [[ + Stop the event loop, causing `uv.run()` to end as soon as possible. This + will happen not sooner than the next loop iteration. If this function was called + before blocking for I/O, the loop won't block for I/O on this iteration. + ]], + }, + { + name = 'backend_fd', + desc = [[ + Get backend file descriptor. Only kqueue, epoll, and event ports are supported. + + This can be used in conjunction with `uv.run("nowait")` to poll in one thread + and run the event loop's callbacks in another + ]], + notes = { + [[ + Embedding a kqueue fd in another kqueue pollset doesn't work on all + platforms. It's not an error to add the fd but it never generates events. ]], }, - { - title = 'Synchronous vs Asynchronous Functions', - desc = [[ - Functions that accept a callback are asynchronous. These functions may - immediately return results to the caller to indicate their initial status, but - their final execution is deferred until at least the next libuv loop iteration. - After completion, their callbacks are executed with any results passed to it. + returns = { { opt_int } }, + }, + { + name = 'backend_timeout', + desc = [[ + Get the poll timeout. The return value is in milliseconds, or -1 for no timeout. + ]], + returns = 'integer', + }, + { + name = 'now', + desc = [[ + Returns the current timestamp in milliseconds. The timestamp is cached at the + start of the event loop tick, see `uv.update_time()` for details and rationale. - Functions that do not accept a callback are synchronous. These functions - immediately return their results to the caller. + The timestamp increases monotonically from some arbitrary point in time. Don't + make assumptions about the starting point, you will only get disappointed. - Some (generally FS and DNS) functions can behave either synchronously or - asynchronously. If a callback is provided to these functions, they behave - asynchronously; if no callback is provided, they behave synchronously. - ]], + ]], + notes = { + 'Use `uv.hrtime()` if you need sub-millisecond granularity.', }, - { - title = 'Pseudo-Types', - desc = [[ - Some unique types are defined. These are not actual types in Lua, but they are - used here to facilitate documenting consistent behavior: - - `fail`: an assertable `nil, string, string` tuple (see [Error Handling][]) - - `callable`: a `function`; or a `table` or `userdata` with a `__call` - metamethod - - `buffer`: a `string` or a sequential `table` of `string`s - - `threadargs`: variable arguments (`...`) of type `nil`, `boolean`, `number`, - `string`, or `userdata`, numbers of argument limited to 9. - ]], + returns = 'integer', + }, + { + name = 'update_time', + desc = [[ + Update the event loop's concept of "now". Libuv caches the current time at the + start of the event loop tick in order to reduce the number of time-related + system calls. + + You won't normally need to call this function unless you have callbacks that + block the event loop for longer periods of time, where "longer" is somewhat + subjective but probably on the order of a millisecond or more. + ]], + }, + { + name = 'walk', + desc = [[ + Walk the list of handles: `callback` will be executed with each handle. + ]], + example = [[ + ```lua + -- Example usage of uv.walk to close all handles that aren't already closing. + uv.walk(function (handle) + if not handle:is_closing() then + handle:close() + end + end) + ``` + ]], + params = { + cb({ { 'handle', 'uv_handle_t' } }), }, }, }, - { - title = 'Contents', - desc = [[ - This documentation is mostly a retelling of the [libuv API documentation][] - within the context of luv's Lua API. Low-level implementation details and - unexposed C functions and types are not documented here except for when they - are relevant to behavior seen in the Lua module. - - - [Constants][] - - [Error Handling][] - - [Version Checking][] - - [`uv_loop_t`][] — Event loop - - [`uv_req_t`][] — Base request - - [`uv_handle_t`][] — Base handle - - [`uv_timer_t`][] — Timer handle - - [`uv_prepare_t`][] — Prepare handle - - [`uv_check_t`][] — Check handle - - [`uv_idle_t`][] — Idle handle - - [`uv_async_t`][] — Async handle - - [`uv_poll_t`][] — Poll handle - - [`uv_signal_t`][] — Signal handle - - [`uv_process_t`][] — Process handle - - [`uv_stream_t`][] — Stream handle - - [`uv_tcp_t`][] — TCP handle - - [`uv_pipe_t`][] — Pipe handle - - [`uv_tty_t`][] — TTY handle - - [`uv_udp_t`][] — UDP handle - - [`uv_fs_event_t`][] — FS Event handle - - [`uv_fs_poll_t`][] — FS Poll handle - - [File system operations][] - - [Thread pool work scheduling][] - - [DNS utility functions][] - - [Threading and synchronization utilities][] - - [Miscellaneous utilities][] - - [Metrics operations][] - ]], - }, - { - title = 'Constants', - id = 'constants', - desc = [[ - As a Lua library, luv supports and encourages the use of lowercase strings to - represent options. For example: - ```lua - -- signal start with string input - uv.signal_start("sigterm", function(signame) - print(signame) -- string output: "sigterm" - end) - ``` - - However, luv also superficially exposes libuv constants in a Lua table at - `uv.constants` where its keys are uppercase constant names and their associated - values are integers defined internally by libuv. The values from this table may - be supported as function arguments, but their use may not change the output - type. For example: - - ```lua - -- signal start with integer input - uv.signal_start(uv.constants.SIGTERM, function(signame) - print(signame) -- string output: "sigterm" - end) - ``` - - The uppercase constants defined in `uv.constants` that have associated - lowercase option strings are listed below. - ]], - sections = { - { - title = 'Address Families', - constants = constants.address_families, - }, - { - title = 'Signals', - constants = constants.signals, + }, + { + title = '`uv_req_t` - Base request', + id = 'uv_req_t--base-request', + class = 'uv_req_t', + desc = '`uv_req_t` is the base type for all libuv request types.', + funcs = { + { + name = 'cancel', + method_form = 'req:cancel()', + desc = [[ + Cancel a pending request. Fails if the request is executing or has finished + executing. Only cancellation of `uv_fs_t`, `uv_getaddrinfo_t`, + `uv_getnameinfo_t` and `uv_work_t` requests is currently supported. + ]], + params = { + { name = 'req', type = 'uv_req_t' }, }, - { - title = 'Socket Types', - constants = constants.socket_types, + returns = success_ret, + }, + { + name = 'req_get_type', + method_form = 'req:get_type()', + desc = [[ + Returns the name of the struct for a given request (e.g. `"fs"` for `uv_fs_t`) + and the libuv enum integer for the request's type (`uv_req_type`). + ]], + params = { + { name = 'req', type = 'uv_req_t' }, }, - { - title = 'TTY Modes', - constants = constants.tty_modes, + returns = { + { 'string', 'type' }, + { 'integer', 'enum' }, }, }, }, - { - title = 'Error Handling', - id = 'error-handling', - desc = [[ - In libuv, errors are represented by negative numbered constants. While these - constants are made available in the `uv.errno` table, they are not returned by - luv functions and the libuv functions used to handle them are not exposed. - Instead, if an internal error is encountered, the failing luv function will - return to the caller an assertable `nil, err, name` tuple: - - - `nil` idiomatically indicates failure - - `err` is a string with the format `{name}: {message}` - - `{name}` is the error name provided internally by `uv_err_name` - - `{message}` is a human-readable message provided internally by `uv_strerror` - - `name` is the same string used to construct `err` - - This tuple is referred to below as the `fail` pseudo-type. - - When a function is called successfully, it will return either a value that is - relevant to the operation of the function, or the integer `0` to indicate - success, or sometimes nothing at all. These cases are documented below. - - Below is a list of known error names and error strings. See libuv's - [error constants][] page for an original source. - - - `E2BIG`: argument list too long. - - `EACCES`: permission denied. - - `EADDRINUSE`: address already in use. - - `EADDRNOTAVAIL`: address not available. - - `EAFNOSUPPORT`: address family not supported. - - `EAGAIN`: resource temporarily unavailable. - - `EAI_ADDRFAMILY`: address family not supported. - - `EAI_AGAIN`: temporary failure. - - `EAI_BADFLAGS`: bad ai_flags value. - - `EAI_BADHINTS`: invalid value for hints. - - `EAI_CANCELED`: request canceled. - - `EAI_FAIL`: permanent failure. - - `EAI_FAMILY`: ai_family not supported. - - `EAI_MEMORY`: out of memory. - - `EAI_NODATA`: no address. - - `EAI_NONAME`: unknown node or service. - - `EAI_OVERFLOW`: argument buffer overflow. - - `EAI_PROTOCOL`: resolved protocol is unknown. - - `EAI_SERVICE`: service not available for socket type. - - `EAI_SOCKTYPE`: socket type not supported. - - `EALREADY`: connection already in progress. - - `EBADF`: bad file descriptor. - - `EBUSY`: resource busy or locked. - - `ECANCELED`: operation canceled. - - `ECHARSET`: invalid Unicode character. - - `ECONNABORTED`: software caused connection abort. - - `ECONNREFUSED`: connection refused. - - `ECONNRESET`: connection reset by peer. - - `EDESTADDRREQ`: destination address required. - - `EEXIST`: file already exists. - - `EFAULT`: bad address in system call argument. - - `EFBIG`: file too large. - - `EHOSTUNREACH`: host is unreachable. - - `EINTR`: interrupted system call. - - `EINVAL`: invalid argument. - - `EIO`: i/o error. - - `EISCONN`: socket is already connected. - - `EISDIR`: illegal operation on a directory. - - `ELOOP`: too many symbolic links encountered. - - `EMFILE`: too many open files. - - `EMSGSIZE`: message too long. - - `ENAMETOOLONG`: name too long. - - `ENETDOWN`: network is down. - - `ENETUNREACH`: network is unreachable. - - `ENFILE`: file table overflow. - - `ENOBUFS`: no buffer space available. - - `ENODEV`: no such device. - - `ENOENT`: no such file or directory. - - `ENOMEM`: not enough memory. - - `ENONET`: machine is not on the network. - - `ENOPROTOOPT`: protocol not available. - - `ENOSPC`: no space left on device. - - `ENOSYS`: function not implemented. - - `ENOTCONN`: socket is not connected. - - `ENOTDIR`: not a directory. - - `ENOTEMPTY`: directory not empty. - - `ENOTSOCK`: socket operation on non-socket. - - `ENOTSUP`: operation not supported on socket. - - `EOVERFLOW`: value too large for defined data type. - - `EPERM`: operation not permitted. - - `EPIPE`: broken pipe. - - `EPROTO`: protocol error. - - `EPROTONOSUPPORT`: protocol not supported. - - `EPROTOTYPE`: protocol wrong type for socket. - - `ERANGE`: result too large. - - `EROFS`: read-only file system. - - `ESHUTDOWN`: cannot send after transport endpoint shutdown. - - `ESPIPE`: invalid seek. - - `ESRCH`: no such process. - - `ETIMEDOUT`: connection timed out. - - `ETXTBSY`: text file is busy. - - `EXDEV`: cross-device link not permitted. - - `UNKNOWN`: unknown error. - - `EOF`: end of file. - - `ENXIO`: no such device or address. - - `EMLINK`: too many links. - - `ENOTTY`: inappropriate ioctl for device. - - `EFTYPE`: inappropriate file type or format. - - `EILSEQ`: illegal byte sequence. - - `ESOCKTNOSUPPORT`: socket type not supported. - ]], - }, - { - title = 'Version Checking', - id = 'version-checking', - methods = { - { - name = 'version', - desc = [[ - Returns the libuv version packed into a single integer. 8 bits are used for each - component, with the patch number stored in the 8 least significant bits. For - example, this would be 0x010203 in libuv 1.2.3. - ]], - returns = 'integer', + }, + { + title = '`uv_handle_t` - Base handle', + id = 'uv_handle_t--base-handle', + class = 'uv_handle_t', + desc = [[ + `uv_handle_t` is the base type for all libuv handle types. All API functions + defined here work with any handle type. + ]], + funcs = { + { + name = 'is_active', + method_form = 'handle:is_active()', + desc = [[ + Returns `true` if the handle is active, `false` if it's inactive. What "active” + means depends on the type of handle: + + - A [`uv_async_t`][] handle is always active and cannot be deactivated, except + by closing it with `uv.close()`. + + - A [`uv_pipe_t`][], [`uv_tcp_t`][], [`uv_udp_t`][], etc. handle - basically + any handle that deals with I/O - is active when it is doing something that + involves I/O, like reading, writing, connecting, accepting new connections, + etc. + + - A [`uv_check_t`][], [`uv_idle_t`][], [`uv_timer_t`][], etc. handle is active + when it has been started with a call to `uv.check_start()`, `uv.idle_start()`, + `uv.timer_start()` etc. until it has been stopped with a call to its + respective stop function. + ]], + params = { + { name = 'handle', type = 'uv_handle_t' }, }, - { - name = 'version_string', - desc = [[ - Returns the libuv version number as a string. For example, this would be "1.2.3" - in libuv 1.2.3. For non-release versions, the version suffix is included. + returns = ret_or_fail('boolean', 'active'), + }, + { + name = 'is_closing', + method_form = 'handle:is_closing()', + desc = [[ + Returns `true` if the handle is closing or closed, `false` otherwise. + ]], + notes = { + [[ + This function should only be used between the initialization of the + handle and the arrival of the close callback. ]], - returns = 'string', }, + params = { + { name = 'handle', type = 'uv_handle_t' }, + }, + returns = ret_or_fail('boolean', 'closing'), }, - }, - { - title = '`uv_loop_t` - Event loop', - id = 'uv_loop_t--event-loop', - desc = [[ - The event loop is the central part of libuv's functionality. It takes care of - polling for I/O and scheduling callbacks to be run based on different sources of - events. - - In luv, there is an implicit uv loop for every Lua state that loads the library. - You can use this library in an multi-threaded environment as long as each thread - has it's own Lua state with its corresponding own uv loop. This loop is not - directly exposed to users in the Lua module. - ]], - methods = { - { - name = 'loop_close', - desc = [[ - Closes all internal loop resources. In normal execution, the loop will - automatically be closed when it is garbage collected by Lua, so it is not - necessary to explicitly call `loop_close()`. Call this function only after the - loop has finished executing and all open handles and requests have been closed, - or it will return `EBUSY`. - ]], - returns = success_ret, + { + name = 'close', + method_form = 'handle:close([callback])', + desc = [[ + Request handle to be closed. `callback` will be called asynchronously after this + call. This MUST be called on each handle before memory is released. + + Handles that wrap file descriptors are closed immediately but `callback` will + still be deferred to the next iteration of the event loop. It gives you a chance + to free up any resources associated with the handle. + + In-progress requests, like `uv_connect_t` or `uv_write_t`, are cancelled and + have their callbacks called asynchronously with `ECANCELED`. + ]], + params = { + { name = 'handle', type = 'uv_handle_t' }, + cb(nil, true), }, - { - name = 'run', - desc = [[ - This function runs the event loop. It will act differently depending on the - specified mode: - - - `"default"`: Runs the event loop until there are no more active and - referenced handles or requests. Returns `true` if `uv.stop()` was called and - there are still active handles or requests. Returns `false` in all other - cases. - - - `"once"`: Poll for I/O once. Note that this function blocks if there are no - pending callbacks. Returns `false` when done (no active handles or requests - left), or `true` if more callbacks are expected (meaning you should run the - event loop again sometime in the future). + }, + { + name = 'ref', + method_form = 'handle:ref()', + desc = [[ + Reference the given handle. References are idempotent, that is, if a handle is + already referenced calling this function again will have no effect. + ]], + see = 'Reference counting', + params = { + { name = 'handle', type = 'uv_handle_t' }, + }, + }, + { + name = 'unref', + method_form = 'handle:unref()', + desc = [[ + Un-reference the given handle. References are idempotent, that is, if a handle + is not referenced calling this function again will have no effect. + ]], + see = 'Reference counting', + params = { + { name = 'handle', type = 'uv_handle_t' }, + }, + }, + { + name = 'has_ref', + method_form = 'handle:has_ref()', + desc = 'Returns `true` if the handle referenced, `false` if not.', + see = 'Reference counting', + params = { + { name = 'handle', type = 'uv_handle_t' }, + }, + returns = ret_or_fail('boolean', 'has_ref'), + }, + { + name = 'send_buffer_size', + method_form = 'handle:send_buffer_size([size])', + desc = [[ + Gets or sets the size of the send buffer that the operating system uses for the + socket. - - `"nowait"`: Poll for I/O once but don't block if there are no pending - callbacks. Returns `false` if done (no active handles or requests left), - or `true` if more callbacks are expected (meaning you should run the event - loop again sometime in the future). + If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. + This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP + handles on Windows. + ]], + notes = { + [[ + Linux will set double the size and return double the size of the + original set value. ]], - notes = { - [[ - Luvit will implicitly call `uv.run()` after loading user code, but if - you use the luv bindings directly, you need to call this after registering - your initial set of event callbacks to start the event loop. - ]], - }, - params = { - { name = 'mode', type = opt('string'), default = '"default"' }, - }, - -- If loop is already running then returns (nil, string) - returns = ret_or_fail('boolean', 'running'), - }, - { - name = 'loop_configure', - desc = [[ - Set additional loop options. You should normally call this before the first call - to uv_run() unless mentioned otherwise. - - Supported options: - - - `"block_signal"`: Block a signal when polling for new events. The second argument - to loop_configure() is the signal name (as a lowercase string) or the signal number. - This operation is currently only implemented for `"sigprof"` signals, to suppress - unnecessary wakeups when using a sampling profiler. Requesting other signals will - fail with `EINVAL`. - - `"metrics_idle_time"`: Accumulate the amount of idle time the event loop spends - in the event provider. This option is necessary to use `metrics_idle_time()`. - - An example of a valid call to this function is: - - ```lua - uv.loop_configure("block_signal", "sigprof") - ``` - ]], - notes = { - [[ - Be prepared to handle the `ENOSYS` error; it means the loop option is - not supported by the platform. - ]], - }, - params = { - { name = 'option', type = 'string' }, - { name = '...', type = 'any', desc = 'depends on `option`' }, - }, - returns = success_ret, - }, - { - name = 'loop_mode', - desc = [[ - If the loop is running, returns a string indicating the mode in use. If the loop - is not running, `nil` is returned instead. - ]], - returns = { { opt('string') } }, }, - { - name = 'loop_alive', - desc = [[ - Returns `true` if there are referenced active handles, active requests, or - closing handles in the loop; otherwise, `false`. - ]], - returns = ret_or_fail('boolean', 'alive'), - }, - { - name = 'stop', - desc = [[ - Stop the event loop, causing `uv.run()` to end as soon as possible. This - will happen not sooner than the next loop iteration. If this function was called - before blocking for I/O, the loop won't block for I/O on this iteration. - ]], + params = { + { name = 'handle', type = 'uv_handle_t' }, + { name = 'size', type = opt_int, default = '0' }, }, - { - name = 'backend_fd', - desc = [[ - Get backend file descriptor. Only kqueue, epoll, and event ports are supported. + returns = ret_or_fail('integer', 'success'), + returns_doc = [[ + - `integer` or `fail` (if `size` is `nil` or `0`) + - `0` or `fail` (if `size` is not `nil` and not `0`) + ]], + }, + { + name = 'recv_buffer_size', + method_form = 'handle:recv_buffer_size([size])', + desc = [[ + Gets or sets the size of the receive buffer that the operating system uses for + the socket. + + If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. - This can be used in conjunction with `uv.run("nowait")` to poll in one thread - and run the event loop's callbacks in another + This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP + handles on Windows. + ]], + notes = { + [[ + Linux will set double the size and return double the size of the + original set value. ]], - notes = { - [[ - Embedding a kqueue fd in another kqueue pollset doesn't work on all - platforms. It's not an error to add the fd but it never generates events. - ]], - }, - returns = { { opt('integer') } }, }, - { - name = 'backend_timeout', - desc = [[ - Get the poll timeout. The return value is in milliseconds, or -1 for no timeout. - ]], - returns = 'integer', + params = { + { name = 'handle', type = 'uv_handle_t' }, + { name = 'size', type = opt_int, default = '0' }, }, - { - name = 'now', - desc = [[ - Returns the current timestamp in milliseconds. The timestamp is cached at the - start of the event loop tick, see `uv.update_time()` for details and rationale. + returns = ret_or_fail('integer', 'success'), + returns_doc = [[ + - `integer` or `fail` (if `size` is `nil` or `0`) + - `0` or `fail` (if `size` is not `nil` and not `0`) + ]], + }, + { + name = 'fileno', + method_form = 'handle:fileno()', + desc = [[ + Gets the platform dependent file descriptor equivalent. - The timestamp increases monotonically from some arbitrary point in time. Don't - make assumptions about the starting point, you will only get disappointed. + The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing any + other handle type will fail with `EINVAL`. - ]], - notes = { - 'Use `uv.hrtime()` if you need sub-millisecond granularity.', - }, - returns = 'integer', - }, - { - name = 'update_time', - desc = [[ - Update the event loop's concept of "now". Libuv caches the current time at the - start of the event loop tick in order to reduce the number of time-related - system calls. - - You won't normally need to call this function unless you have callbacks that - block the event loop for longer periods of time, where "longer" is somewhat - subjective but probably on the order of a millisecond or more. + If a handle doesn't have an attached file descriptor yet or the handle itself + has been closed, this function will return `EBADF`. + ]], + warnings = { + [[ + Be very careful when using this function. libuv assumes it's in + control of the file descriptor so any change to it may lead to malfunction. ]], }, - { - name = 'walk', - desc = [[ - Walk the list of handles: `callback` will be executed with each handle. - ]], - example = [[ - ```lua - -- Example usage of uv.walk to close all handles that aren't already closing. - uv.walk(function (handle) - if not handle:is_closing() then - handle:close() - end - end) - ``` - ]], - params = { - cb({ { 'handle', 'uv_handle_t' } }), - }, + params = { + { name = 'handle', type = 'uv_handle_t' }, }, + returns = ret_or_fail('integer', 'fileno'), }, - }, - { - title = '`uv_req_t` - Base request', - id = 'uv_req_t--base-request', - desc = '`uv_req_t` is the base type for all libuv request types.', - methods = { - { - name = 'cancel', - method_form = 'req:cancel()', - desc = [[ - Cancel a pending request. Fails if the request is executing or has finished - executing. Only cancellation of `uv_fs_t`, `uv_getaddrinfo_t`, - `uv_getnameinfo_t` and `uv_work_t` requests is currently supported. - ]], - params = { - { name = 'req', type = 'uv_req_t' }, - }, - returns = success_ret, - }, - { - name = 'req_get_type', - method_form = 'req:get_type()', - desc = [[ - Returns the name of the struct for a given request (e.g. `"fs"` for `uv_fs_t`) - and the libuv enum integer for the request's type (`uv_req_type`). - ]], - params = { - { name = 'req', type = 'uv_req_t' }, - }, - returns = { - { 'string', 'type' }, - { 'integer', 'enum' }, - }, + { + name = 'handle_get_type', + method_form = 'handle:get_type()', + desc = [[ + Returns the name of the struct for a given handle (e.g. `"pipe"` for `uv_pipe_t`) + and the libuv enum integer for the handle's type (`uv_handle_type`). + ]], + params = { + { name = 'handle', type = 'uv_handle_t' }, + }, + returns = { + { 'string', 'type' }, + { 'integer', 'enum' }, }, }, }, - { - title = '`uv_handle_t` - Base handle', - id = 'uv_handle_t--base-handle', - desc = [[ - `uv_handle_t` is the base type for all libuv handle types. All API functions - defined here work with any handle type. - ]], - methods = { - { - name = 'is_active', - method_form = 'handle:is_active()', - desc = [[ - Returns `true` if the handle is active, `false` if it's inactive. What "active” - means depends on the type of handle: - - - A [`uv_async_t`][] handle is always active and cannot be deactivated, except - by closing it with `uv.close()`. - - - A [`uv_pipe_t`][], [`uv_tcp_t`][], [`uv_udp_t`][], etc. handle - basically - any handle that deals with I/O - is active when it is doing something that - involves I/O, like reading, writing, connecting, accepting new connections, - etc. - - - A [`uv_check_t`][], [`uv_idle_t`][], [`uv_timer_t`][], etc. handle is active - when it has been started with a call to `uv.check_start()`, `uv.idle_start()`, - `uv.timer_start()` etc. until it has been stopped with a call to its - respective stop function. - ]], - params = { - { name = 'handle', type = 'uv_handle_t' }, - }, - returns = ret_or_fail('boolean', 'active'), + }, + { + title = 'Reference counting', + id = 'reference-counting', + desc = [[ + The libuv event loop (if run in the default mode) will run until there are no + active and referenced handles left. The user can force the loop to exit early by + unreferencing handles which are active, for example by calling `uv.unref()` + after calling `uv.timer_start()`. + + A handle can be referenced or unreferenced, the refcounting scheme doesn't use a + counter, so both operations are idempotent. + + All handles are referenced when active by default, see `uv.is_active()` for a + more detailed explanation on what being active involves. + ]], + }, + { + title = '`uv_timer_t` - Timer handle', + id = 'uv_timer_t--timer-handle', + class = 'uv_timer_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Timer handles are used to schedule callbacks to be called in the future. + ]], + funcs = { + { + name = 'new_timer', + desc = [[ + Creates and initializes a new `uv_timer_t`. Returns the Lua userdata wrapping + it. + ]], + example = [[ + ```lua + -- Creating a simple setTimeout wrapper + local function setTimeout(timeout, callback) + local timer = uv.new_timer() + timer:start(timeout, 0, function () + timer:stop() + timer:close() + callback() + end) + return timer + end + + -- Creating a simple setInterval wrapper + local function setInterval(interval, callback) + local timer = uv.new_timer() + timer:start(interval, interval, function () + callback() + end) + return timer + end + + -- And clearInterval + local function clearInterval(timer) + timer:stop() + timer:close() + end + ``` + ]], + returns = ret_or_fail('uv_timer_t', 'timer'), + }, + { + name = 'timer_start', + method_form = 'timer:start(timeout, repeat, callback)', + desc = [[ + Start the timer. `timeout` and `repeat` are in milliseconds. + + If `timeout` is zero, the callback fires on the next event loop iteration. If + `repeat` is non-zero, the callback fires first after `timeout` milliseconds and + then repeatedly after `repeat` milliseconds. + ]], + params = { + { name = 'timer', type = 'uv_timer_t' }, + { name = 'timeout', type = 'integer' }, + { name = 'repeat', type = 'integer' }, + cb(), }, - { - name = 'is_closing', - method_form = 'handle:is_closing()', - desc = [[ - Returns `true` if the handle is closing or closed, `false` otherwise. - ]], - notes = { - [[ - This function should only be used between the initialization of the - handle and the arrival of the close callback. - ]], - }, - params = { - { name = 'handle', type = 'uv_handle_t' }, - }, - returns = ret_or_fail('boolean', 'closing'), + returns = success_ret, + }, + { + name = 'timer_stop', + method_form = 'timer:stop()', + desc = 'Stop the timer, the callback will not be called anymore.', + params = { + { name = 'timer', type = 'uv_timer_t' }, + }, + returns = success_ret, + }, + { + name = 'timer_again', + method_form = 'timer:again()', + desc = [[ + Stop the timer, and if it is repeating restart it using the repeat value as the + timeout. If the timer has never been started before it raises `EINVAL`. + ]], + params = { + { name = 'timer', type = 'uv_timer_t' }, }, - { - name = 'close', - method_form = 'handle:close([callback])', - desc = [[ - Request handle to be closed. `callback` will be called asynchronously after this - call. This MUST be called on each handle before memory is released. - - Handles that wrap file descriptors are closed immediately but `callback` will - still be deferred to the next iteration of the event loop. It gives you a chance - to free up any resources associated with the handle. + returns = success_ret, + }, + { + name = 'timer_set_repeat', + method_form = 'timer:set_repeat(repeat)', + desc = [[ + Set the repeat interval value in milliseconds. The timer will be scheduled to + run on the given interval, regardless of the callback execution duration, and + will follow normal timer semantics in the case of a time-slice overrun. + + For example, if a 50 ms repeating timer first runs for 17 ms, it will be + scheduled to run again 33 ms later. If other tasks consume more than the 33 ms + following the first timer callback, then the callback will run as soon as + possible. - In-progress requests, like `uv_connect_t` or `uv_write_t`, are cancelled and - have their callbacks called asynchronously with `ECANCELED`. - ]], - params = { - { name = 'handle', type = 'uv_handle_t' }, - cb(nil, true), - }, + ]], + params = { + { name = 'timer', type = 'uv_timer_t' }, + { name = 'repeat', type = 'integer' }, }, - { - name = 'ref', - method_form = 'handle:ref()', - desc = [[ - Reference the given handle. References are idempotent, that is, if a handle is - already referenced calling this function again will have no effect. - ]], - see = 'Reference counting', - params = { - { name = 'handle', type = 'uv_handle_t' }, - }, + }, + { + name = 'timer_get_repeat', + method_form = 'timer:get_repeat()', + desc = 'Get the timer repeat value.', + params = { + { name = 'timer', type = 'uv_timer_t' }, + }, + returns = { { 'integer', 'repeat' } }, + }, + { + name = 'timer_get_due_in', + method_form = 'timer:get_due_in()', + desc = [[ + Get the timer due value or 0 if it has expired. The time is relative to `uv.now()`. + ]], + since = '1.40.0', + params = { + { name = 'timer', type = 'uv_timer_t' }, }, - { - name = 'unref', - method_form = 'handle:unref()', - desc = [[ - Un-reference the given handle. References are idempotent, that is, if a handle - is not referenced calling this function again will have no effect. + returns = { { 'integer', 'due_in' } }, + }, + }, + }, + { + title = '`uv_prepare_t` - Prepare handle', + id = 'uv_prepare_t--prepare-handle', + class = 'uv_prepare_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Prepare handles will run the given callback once per loop iteration, right + before polling for I/O. + + ```lua + local prepare = uv.new_prepare() + prepare:start(function() + print("Before I/O polling") + end) + ``` + ]], + funcs = { + { + name = 'new_prepare', + desc = [[ + Creates and initializes a new `uv_prepare_t`. Returns the Lua userdata wrapping + it. + ]], + returns = 'uv_prepare_t', + }, + { + name = 'prepare_start', + method_form = 'prepare:start(callback)', + desc = 'Start the handle with the given callback.', + params = { + { name = 'prepare', type = 'uv_prepare_t' }, + cb(), + }, + returns = success_ret, + }, + { + name = 'prepare_stop', + method_form = 'prepare:stop()', + desc = 'Stop the handle, the callback will no longer be called.', + params = { + { name = 'prepare', type = 'uv_prepare_t' }, + }, + returns = success_ret, + }, + }, + }, + { + title = '`uv_check_t` - Check handle', + id = 'uv_check_t--check-handle', + class = 'uv_check_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Check handles will run the given callback once per loop iteration, right after + polling for I/O. + + ```lua + local check = uv.new_check() + check:start(function() + print("After I/O polling") + end) + ``` + ]], + funcs = { + { + name = 'new_check', + desc = [[ + Creates and initializes a new `uv_check_t`. Returns the Lua userdata wrapping + it. + ]], + returns = 'uv_check_t', + }, + { + name = 'check_start', + method_form = 'check:start(callback)', + desc = 'Start the handle with the given callback.', + params = { + { name = 'check', type = 'uv_check_t' }, + cb(), + }, + returns = success_ret, + }, + { + name = 'check_stop', + method_form = 'check:stop()', + desc = 'Stop the handle, the callback will no longer be called.', + params = { + { name = 'check', type = 'uv_check_t' }, + }, + returns = success_ret, + }, + }, + }, + { + title = '`uv_idle_t` - Idle handle', + id = 'uv_idle_t--idle-handle', + class = 'uv_idle_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Idle handles will run the given callback once per loop iteration, right before + the [`uv_prepare_t`][] handles. + + **Note**: The notable difference with prepare handles is that when there are + active idle handles, the loop will perform a zero timeout poll instead of + blocking for I/O. + + **Warning**: Despite the name, idle handles will get their callbacks called on + every loop iteration, not when the loop is actually "idle". + + ```lua + local idle = uv.new_idle() + idle:start(function() + print("Before I/O polling, no blocking") + end) + ``` + ]], + funcs = { + { + name = 'new_idle', + desc = [[ + Creates and initializes a new `uv_idle_t`. Returns the Lua userdata wrapping + it. + ]], + returns = 'uv_idle_t', + }, + { + name = 'idle_start', + method_form = 'idle:start(callback)', + desc = 'Start the handle with the given callback.', + params = { + { name = 'idle', type = 'uv_idle_t' }, + cb(), + }, + returns = success_ret, + }, + { + name = 'idle_stop', + method_form = 'idle:stop()', + desc = 'Stop the handle, the callback will no longer be called.', + params = { + { name = 'idle', type = 'uv_idle_t' }, + }, + returns = success_ret, + }, + }, + }, + { + title = '`uv_async_t` - Async handle', + id = 'uv_async_t--async-handle', + class = 'uv_async_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Async handles allow the user to "wakeup" the event loop and get a callback + called from another thread. + + ```lua + local async + async = uv.new_async(function() + print("async operation ran") + async:close() + end) + + async:send() + ``` + ]], + funcs = { + { + name = 'new_async', + desc = [[ + Creates and initializes a new `uv_async_t`. Returns the Lua userdata wrapping + it. + ]], + notes = { + [[ + Unlike other handle initialization functions, this immediately starts + the handle. ]], - see = 'Reference counting', - params = { - { name = 'handle', type = 'uv_handle_t' }, - }, }, - { - name = 'has_ref', - method_form = 'handle:has_ref()', - desc = 'Returns `true` if the handle referenced, `false` if not.', - see = 'Reference counting', - params = { - { name = 'handle', type = 'uv_handle_t' }, + params = { + { + name = 'callback', + type = fun({ + { '...', 'threadargs', 'passed to/from `uv.async_send(async, ...)`' }, + }), }, - returns = ret_or_fail('boolean', 'has_ref'), }, - { - name = 'send_buffer_size', - method_form = 'handle:send_buffer_size([size])', - desc = [[ - Gets or sets the size of the send buffer that the operating system uses for the - socket. + returns = ret_or_fail('uv_async_t', 'async'), + }, + { + name = 'async_send', + method_form = 'async:send(...)', + desc = "Wakeup the event loop and call the async handle's callback.", + notes = { + [[ + It's safe to call this function from any thread. The callback will be + called on the loop thread. + ]], + }, + warnings = { + [[ + libuv will coalesce calls to `uv.async_send(async)`, that is, not + every call to it will yield an execution of the callback. For example: if + `uv.async_send()` is called 5 times in a row before the callback is called, the + callback will only be called once. If `uv.async_send()` is called again after + the callback was called, it will be called again. + ]], + }, + params = { + { name = 'async', type = 'uv_async_t' }, + { name = '...', type = 'threadargs' }, + }, + returns = success_ret, + }, + }, + }, + { + title = '`uv_poll_t` - Poll handle', + id = 'uv_poll_t--poll-handle', + class = 'uv_poll_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Poll handles are used to watch file descriptors for readability and writability, + similar to the purpose of [poll(2)](http://linux.die.net/man/2/poll). + + The purpose of poll handles is to enable integrating external libraries that + rely on the event loop to signal it about the socket status changes, like c-ares + or libssh2. Using `uv_poll_t` for any other purpose is not recommended; + `uv_tcp_t`, `uv_udp_t`, etc. provide an implementation that is faster and more + scalable than what can be achieved with `uv_poll_t`, especially on Windows. + + It is possible that poll handles occasionally signal that a file descriptor is + readable or writable even when it isn't. The user should therefore always be + prepared to handle EAGAIN or equivalent when it attempts to read from or write + to the fd. + + It is not okay to have multiple active poll handles for the same socket, this + can cause libuv to busyloop or otherwise malfunction. + + The user should not close a file descriptor while it is being polled by an + active poll handle. This can cause the handle to report an error, but it might + also start polling another socket. However the fd can be safely closed + immediately after a call to `uv.poll_stop()` or `uv.close()`. + + **Note**: On windows only sockets can be polled with poll handles. On Unix any + file descriptor that would be accepted by poll(2) can be used. + ]], + funcs = { + { + name = 'new_poll', + desc = [[ + Initialize the handle using a file descriptor. + + The file descriptor is set to non-blocking mode. + ]], + params = { + { name = 'fd', type = 'integer' }, + }, + returns = ret_or_fail('uv_poll_t', 'poll'), + }, + { + name = 'new_socket_poll', + desc = [[ + Initialize the handle using a socket descriptor. On Unix this is identical to + `uv.new_poll()`. On windows it takes a SOCKET handle. - If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. + The socket is set to non-blocking mode. + ]], + params = { + { name = 'fd', type = 'integer' }, + }, + returns = ret_or_fail('uv_poll_t', 'poll'), + }, + { + name = 'poll_start', + method_form = 'poll:start(events, callback)', + desc = [[ + Starts polling the file descriptor. `events` are: `"r"`, `"w"`, `"rw"`, `"d"`, + `"rd"`, `"wd"`, `"rwd"`, `"p"`, `"rp"`, `"wp"`, `"rwp"`, `"dp"`, `"rdp"`, + `"wdp"`, or `"rwdp"` where `r` is `READABLE`, `w` is `WRITABLE`, `d` is + `DISCONNECT`, and `p` is `PRIORITIZED`. As soon as an event is detected + the callback will be called with status set to 0, and the detected events set on + the events field. + + The user should not close the socket while the handle is active. If the user + does that anyway, the callback may be called reporting an error status, but this + is not guaranteed. - This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP - handles on Windows. - ]], - notes = { - [[ - Linux will set double the size and return double the size of the - original set value. - ]], - }, - params = { - { name = 'handle', type = 'uv_handle_t' }, - { name = 'size', type = opt('integer'), default = '0' }, + ]], + notes = { + [[ + Calling `uv.poll_start()` on a handle that is already active is fine. + Doing so will update the events mask that is being watched for. + ]], + }, + params = { + { name = 'poll', type = 'uv_poll_t' }, + { name = 'events', type = opt_str, default = '"rw"' }, + { + name = 'callback', + type = fun({ + { 'err', opt_str }, + { 'events', opt_str }, + }), }, - returns = ret_or_fail('integer', 'success'), - returns_doc = [[ - - `integer` or `fail` (if `size` is `nil` or `0`) - - `0` or `fail` (if `size` is not `nil` and not `0`) - ]], }, - { - name = 'recv_buffer_size', - method_form = 'handle:recv_buffer_size([size])', - desc = [[ - Gets or sets the size of the receive buffer that the operating system uses for - the socket. - - If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. + returns = success_ret, + }, + { + name = 'poll_stop', + method_form = 'poll:stop()', + desc = [[ + Stop polling the file descriptor, the callback will no longer be called. + ]], + params = { + { name = 'poll', type = 'uv_poll_t' }, + }, + returns = success_ret, + }, + }, + }, + { + title = '`uv_signal_t` - Signal handle', + id = 'uv_signal_t--signal-handle', + class = 'uv_signal_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Signal handles implement Unix style signal handling on a per-event loop bases. + + **Windows Notes:** + + Reception of some signals is emulated on Windows: + - SIGINT is normally delivered when the user presses CTRL+C. However, like on + Unix, it is not generated when terminal raw mode is enabled. + - SIGBREAK is delivered when the user pressed CTRL + BREAK. + - SIGHUP is generated when the user closes the console window. On SIGHUP the + program is given approximately 10 seconds to perform cleanup. After that + Windows will unconditionally terminate it. + - SIGWINCH is raised whenever libuv detects that the console has been resized. + SIGWINCH is emulated by libuv when the program uses a uv_tty_t handle to write + to the console. SIGWINCH may not always be delivered in a timely manner; libuv + will only detect size changes when the cursor is being moved. When a readable + [`uv_tty_t`][] handle is used in raw mode, resizing the console buffer will + also trigger a SIGWINCH signal. + - Watchers for other signals can be successfully created, but these signals + are never received. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV, + SIGTERM and SIGKILL. + - Calls to raise() or abort() to programmatically raise a signal are not + detected by libuv; these will not trigger a signal watcher. + + **Unix Notes:** + + - SIGKILL and SIGSTOP are impossible to catch. + - Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined + behavior. + - SIGABRT will not be caught by libuv if generated by abort(), e.g. through + assert(). + - On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads + library to manage threads. Installing watchers for those signals will lead to + unpredictable behavior and is strongly discouraged. Future versions of libuv + may simply reject them. + + ```lua + -- Create a new signal handler + local signal = uv.new_signal() + -- Define a handler function + uv.signal_start(signal, "sigint", function(signame) + print("got " .. signame .. ", shutting down") + os.exit(1) + end) + ``` + ]], + funcs = { + { + name = 'new_signal', + desc = [[ + Creates and initializes a new `uv_signal_t`. Returns the Lua userdata wrapping + it. + ]], + returns = ret_or_fail('uv_signal_t', 'signal'), + }, + { + name = 'signal_start', + method_form = 'signal:start(signame, callback)', + desc = [[ + Start the handle with the given callback, watching for the given signal. - This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP - handles on Windows. - ]], - notes = { - [[ - Linux will set double the size and return double the size of the - original set value. - ]], - }, - params = { - { name = 'handle', type = 'uv_handle_t' }, - { name = 'size', type = opt('integer'), default = '0' }, + See [Constants][] for supported `signame` input and output values. + ]], + params = { + { name = 'signal', type = 'uv_signal_t' }, + { name = 'signame', type = 'string|integer' }, + { + name = 'callback', + type = fun({ { 'signame', 'string' } }), }, - returns = ret_or_fail('integer', 'success'), - returns_doc = [[ - - `integer` or `fail` (if `size` is `nil` or `0`) - - `0` or `fail` (if `size` is not `nil` and not `0`) - ]], }, - { - name = 'fileno', - method_form = 'handle:fileno()', - desc = [[ - Gets the platform dependent file descriptor equivalent. - - The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing any - other handle type will fail with `EINVAL`. + returns = success_ret, + }, + { + name = 'signal_start_oneshot', + method_form = 'signal:start_oneshot(signame, callback)', + desc = [[ + Same functionality as `uv.signal_start()` but the signal handler is reset the moment the signal is received. - If a handle doesn't have an attached file descriptor yet or the handle itself - has been closed, this function will return `EBADF`. - ]], - warnings = { - [[ - Be very careful when using this function. libuv assumes it's in - control of the file descriptor so any change to it may lead to malfunction. - ]], - }, - params = { - { name = 'handle', type = 'uv_handle_t' }, - }, - returns = ret_or_fail('integer', 'fileno'), - }, - { - name = 'handle_get_type', - method_form = 'handle:get_type()', - desc = [[ - Returns the name of the struct for a given handle (e.g. `"pipe"` for `uv_pipe_t`) - and the libuv enum integer for the handle's type (`uv_handle_type`). - ]], - params = { - { name = 'handle', type = 'uv_handle_t' }, - }, - returns = { - { 'string', 'type' }, - { 'integer', 'enum' }, + See [Constants][] for supported `signame` input and output values. + ]], + params = { + { name = 'signal', type = 'uv_signal_t' }, + { name = 'signame', type = 'string|integer' }, + { + name = 'callback', + type = fun({ { 'signame', 'string' } }), }, }, + returns = success_ret, + }, + { + name = 'signal_stop', + method_form = 'signal:stop()', + desc = 'Stop the handle, the callback will no longer be called.', + params = { + { name = 'signal', type = 'uv_signal_t' }, + }, + returns = success_ret, }, }, - { - title = 'Reference counting', - id = 'reference-counting', - desc = [[ - The libuv event loop (if run in the default mode) will run until there are no - active and referenced handles left. The user can force the loop to exit early by - unreferencing handles which are active, for example by calling `uv.unref()` - after calling `uv.timer_start()`. - - A handle can be referenced or unreferenced, the refcounting scheme doesn't use a - counter, so both operations are idempotent. - - All handles are referenced when active by default, see `uv.is_active()` for a - more detailed explanation on what being active involves. - ]], - }, - { - title = '`uv_timer_t` - Timer handle', - id = 'uv_timer_t--timer-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Timer handles are used to schedule callbacks to be called in the future. - ]], - methods = { - { - name = 'new_timer', - desc = [[ - Creates and initializes a new `uv_timer_t`. Returns the Lua userdata wrapping - it. + }, + { + title = '`uv_process_t` - Process handle', + id = 'uv_process_t--process-handle', + class = 'uv_process_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Process handles will spawn a new process and allow the user to control it and + establish communication channels with it using streams. + ]], + funcs = { + { + name = 'disable_stdio_inheritance', + desc = [[ + Disables inheritance for file descriptors / handles that this process inherited + from its parent. The effect is that child processes spawned by this process + don't accidentally inherit these handles. + + It is recommended to call this function as early in your program as possible, + before the inherited file descriptors can be closed or duplicated. + ]], + notes = { + [[ + This function works on a best-effort basis: there is no guarantee that + libuv can discover all file descriptors that were inherited. In general it does + a better job on Windows than it does on Unix. ]], - example = [[ - ```lua - -- Creating a simple setTimeout wrapper - local function setTimeout(timeout, callback) - local timer = uv.new_timer() - timer:start(timeout, 0, function () - timer:stop() - timer:close() - callback() - end) - return timer - end + }, + }, + { + name = 'spawn', + desc = [[ + Initializes the process handle and starts the process. If the process is + successfully spawned, this function will return the handle and pid of the child + process. + + Possible reasons for failing to spawn would include (but not be limited to) the + file to execute not existing, not having permissions to use the setuid or setgid + specified, or not having enough memory to allocate for the new process. + + ```lua + local stdin = uv.new_pipe() + local stdout = uv.new_pipe() + local stderr = uv.new_pipe() + + print("stdin", stdin) + print("stdout", stdout) + print("stderr", stderr) + + local handle, pid = uv.spawn("cat", { + stdio = {stdin, stdout, stderr} + }, function(code, signal) -- on exit + print("exit code", code) + print("exit signal", signal) + end) - -- Creating a simple setInterval wrapper - local function setInterval(interval, callback) - local timer = uv.new_timer() - timer:start(interval, interval, function () - callback() - end) - return timer + print("process opened", handle, pid) + + uv.read_start(stdout, function(err, data) + assert(not err, err) + if data then + print("stdout chunk", stdout, data) + else + print("stdout end", stdout) end + end) - -- And clearInterval - local function clearInterval(timer) - timer:stop() - timer:close() + uv.read_start(stderr, function(err, data) + assert(not err, err) + if data then + print("stderr chunk", stderr, data) + else + print("stderr end", stderr) end - ``` - ]], - returns = ret_or_fail('uv_timer_t', 'timer'), - }, - { - name = 'timer_start', - method_form = 'timer:start(timeout, repeat, callback)', - desc = [[ - Start the timer. `timeout` and `repeat` are in milliseconds. + end) - If `timeout` is zero, the callback fires on the next event loop iteration. If - `repeat` is non-zero, the callback fires first after `timeout` milliseconds and - then repeatedly after `repeat` milliseconds. - ]], - params = { - { name = 'timer', type = 'uv_timer_t' }, - { name = 'timeout', type = 'integer' }, - { name = 'repeat', type = 'integer' }, - cb(), - }, - returns = success_ret, - }, - { - name = 'timer_stop', - method_form = 'timer:stop()', - desc = 'Stop the timer, the callback will not be called anymore.', - params = { - { name = 'timer', type = 'uv_timer_t' }, - }, - returns = success_ret, - }, - { - name = 'timer_again', - method_form = 'timer:again()', - desc = [[ - Stop the timer, and if it is repeating restart it using the repeat value as the - timeout. If the timer has never been started before it raises `EINVAL`. - ]], - params = { - { name = 'timer', type = 'uv_timer_t' }, - }, - returns = success_ret, - }, - { - name = 'timer_set_repeat', - method_form = 'timer:set_repeat(repeat)', - desc = [[ - Set the repeat interval value in milliseconds. The timer will be scheduled to - run on the given interval, regardless of the callback execution duration, and - will follow normal timer semantics in the case of a time-slice overrun. + uv.write(stdin, "Hello World") - For example, if a 50 ms repeating timer first runs for 17 ms, it will be - scheduled to run again 33 ms later. If other tasks consume more than the 33 ms - following the first timer callback, then the callback will run as soon as - possible. + uv.shutdown(stdin, function() + print("stdin shutdown", stdin) + uv.close(handle, function() + print("process closed", handle, pid) + end) + end) + ``` - ]], - params = { - { name = 'timer', type = 'uv_timer_t' }, - { name = 'repeat', type = 'integer' }, + When the child process exits, `on_exit` is called with an exit code and signal. + ]], + params = { + { name = 'path', type = 'string' }, + { + name = 'options', + type = table({ + { + 'args', + opt('string[]'), + nil, + [[ + Command line arguments as a list of strings. The first + string should *not* be the path to the program, since that is already + provided via `path`. On Windows, this uses CreateProcess which concatenates + the arguments into a string. This can cause some strange errors + (see `options.verbatim` below for Windows). + ]], + }, + { + 'stdio', + opt(dict('integer', opt(union('integer', 'uv_stream_t')))), + nil, + [[ + Set the file descriptors that will be made available to + the child process. The convention is that the first entries are stdin, stdout, + and stderr. + + The entries can take many shapes. + - If `integer`, then the child process inherits that same zero-indexed + fd from the parent process. + - If `uv_stream_t` handles are passed in, those are used as a read-write pipe + or inherited stream depending if the stream has a valid fd. + - If `nil`, means to ignore that fd in the child process. + + **Note**: On Windows, file descriptors after the third are + available to the child process only if the child processes uses the MSVCRT + runtime. + ]], + }, + { + 'env', + opt(dict('string', 'string')), + nil, + 'Set environment variables for the new process.', + }, + { + 'cwd', + opt_str, + nil, + 'Set the current working directory for the sub-process.', + }, + { + 'uid', + opt_str, + nil, + "Set the child process' user id.", + }, + { + 'gid', + opt_str, + nil, + "Set the child process' group id.", + }, + { + 'verbatim', + opt_bool, + nil, + [[ + If true, do not wrap any arguments in quotes, or + perform any other escaping, when converting the argument list into a command + line string. This option is only meaningful on Windows systems. On Unix it is + silently ignored. + ]], + }, + { + 'detached', + opt_bool, + nil, + [[ + If true, spawn the child process in a detached state - + this will make it a process group leader, and will effectively enable the + child to keep running after the parent exits. Note that the child process + will still keep the parent's event loop alive unless the parent process calls + `uv.unref()` on the child's process handle. + ]], + }, + { + 'hide', + opt_bool, + nil, + [[ + If true, hide the subprocess console window that would + normally be created. This option is only meaningful on Windows systems. On + Unix it is silently ignored. + ]], + }, + }), }, - }, - { - name = 'timer_get_repeat', - method_form = 'timer:get_repeat()', - desc = 'Get the timer repeat value.', - params = { - { name = 'timer', type = 'uv_timer_t' }, + { + name = 'on_exit', + type = fun({ { 'code', 'integer' }, { 'signal', 'integer' } }), }, - returns = { { 'integer', 'repeat' } }, }, - { - name = 'timer_get_due_in', - method_form = 'timer:get_due_in()', - desc = [[ - Get the timer due value or 0 if it has expired. The time is relative to `uv.now()`. - ]], - since = '1.40.0', - params = { - { name = 'timer', type = 'uv_timer_t' }, - }, - returns = { { 'integer', 'due_in' } }, + returns = { + { 'uv_process_t', 'handle' }, + { 'integer', 'pid' }, }, }, - }, - { - title = '`uv_prepare_t` - Prepare handle', - id = 'uv_prepare_t--prepare-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Prepare handles will run the given callback once per loop iteration, right - before polling for I/O. - - ```lua - local prepare = uv.new_prepare() - prepare:start(function() - print("Before I/O polling") - end) - ``` - ]], - methods = { - { - name = 'new_prepare', - desc = [[ - Creates and initializes a new `uv_prepare_t`. Returns the Lua userdata wrapping - it. - ]], - returns = 'uv_prepare_t', - }, - { - name = 'prepare_start', - method_form = 'prepare:start(callback)', - desc = 'Start the handle with the given callback.', - params = { - { name = 'prepare', type = 'uv_prepare_t' }, - cb(), - }, - returns = success_ret, - }, - { - name = 'prepare_stop', - method_form = 'prepare:stop()', - desc = 'Stop the handle, the callback will no longer be called.', - params = { - { name = 'prepare', type = 'uv_prepare_t' }, - }, - returns = success_ret, + { + name = 'process_kill', + method_form = 'process:kill(signame)', + desc = [[ + Sends the specified signal to the given process handle. Check the documentation + on `uv_signal_t` for signal support, specially on Windows. + + See [Constants][] for supported `signame` input values. + ]], + params = { + { name = 'process', type = 'uv_process_t' }, + { name = 'signame', type = opt(union('string', 'integer')), default = 'sigterm' }, }, + returns = success_ret, }, - }, - { - title = '`uv_check_t` - Check handle', - id = 'uv_check_t--check-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Check handles will run the given callback once per loop iteration, right after - polling for I/O. - - ```lua - local check = uv.new_check() - check:start(function() - print("After I/O polling") - end) - ``` - ]], - methods = { - { - name = 'new_check', - desc = [[ - Creates and initializes a new `uv_check_t`. Returns the Lua userdata wrapping - it. - ]], - returns = 'uv_check_t', - }, - { - name = 'check_start', - method_form = 'check:start(callback)', - desc = 'Start the handle with the given callback.', - params = { - { name = 'check', type = 'uv_check_t' }, - cb(), - }, - returns = success_ret, - }, - { - name = 'check_stop', - method_form = 'check:stop()', - desc = 'Stop the handle, the callback will no longer be called.', - params = { - { name = 'check', type = 'uv_check_t' }, - }, - returns = success_ret, + { + name = 'kill', + desc = [[ + Sends the specified signal to the given PID. Check the documentation on + `uv_signal_t` for signal support, specially on Windows. + + See [Constants][] for supported `signame` input values. + ]], + params = { + { name = 'pid', type = 'integer' }, + { name = 'signame', type = opt(union('string', 'integer')), default = 'sigterm' }, }, + returns = success_ret, + }, + { + name = 'process_get_pid', + method_form = 'process:get_pid()', + desc = "Returns the handle's pid.", + params = { + { name = 'process', type = 'uv_process_t' }, + }, + returns = 'integer', }, }, - { - title = '`uv_idle_t` - Idle handle', - id = 'uv_idle_t--idle-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Idle handles will run the given callback once per loop iteration, right before - the [`uv_prepare_t`][] handles. - - **Note**: The notable difference with prepare handles is that when there are - active idle handles, the loop will perform a zero timeout poll instead of - blocking for I/O. - - **Warning**: Despite the name, idle handles will get their callbacks called on - every loop iteration, not when the loop is actually "idle". - - ```lua - local idle = uv.new_idle() - idle:start(function() - print("Before I/O polling, no blocking") - end) - ``` - ]], - methods = { - { - name = 'new_idle', - desc = [[ - Creates and initializes a new `uv_idle_t`. Returns the Lua userdata wrapping - it. - ]], - returns = 'uv_idle_t', - }, - { - name = 'idle_start', - method_form = 'idle:start(callback)', - desc = 'Start the handle with the given callback.', - params = { - { name = 'idle', type = 'uv_idle_t' }, - cb(), - }, - returns = success_ret, - }, - { - name = 'idle_stop', - method_form = 'idle:stop()', - desc = 'Stop the handle, the callback will no longer be called.', - params = { - { name = 'idle', type = 'uv_idle_t' }, - }, - returns = success_ret, + }, + { + title = '`uv_stream_t` - Stream handle', + id = 'uv_stream_t--stream-handle', + class = 'uv_stream_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + Stream handles provide an abstraction of a duplex communication channel. + [`uv_stream_t`][] is an abstract type, libuv provides 3 stream implementations + in the form of [`uv_tcp_t`][], [`uv_pipe_t`][] and [`uv_tty_t`][]. + ]], + funcs = { + { + name = 'shutdown', + method_form = 'stream:shutdown([callback])', + desc = [[ + Shutdown the outgoing (write) side of a duplex stream. It waits for pending + write requests to complete. The callback is called after shutdown is complete. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + cb_err({}, true), }, + returns = ret_or_fail('uv_shutdown_t', 'shutdown'), }, - }, - { - title = '`uv_async_t` - Async handle', - id = 'uv_async_t--async-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Async handles allow the user to "wakeup" the event loop and get a callback - called from another thread. - - ```lua - local async - async = uv.new_async(function() - print("async operation ran") - async:close() - end) - - async:send() - ``` - ]], - methods = { - { - name = 'new_async', - desc = [[ - Creates and initializes a new `uv_async_t`. Returns the Lua userdata wrapping - it. - ]], - notes = { - [[ - Unlike other handle initialization functions, this immediately starts - the handle. - ]], - }, - params = { - { - name = 'callback', - type = fun({ - { '...', 'threadargs', 'passed to/from `uv.async_send(async, ...)`' }, - }), - }, - }, - returns = ret_or_fail('uv_async_t', 'async'), - }, - { - name = 'async_send', - method_form = 'async:send(...)', - desc = "Wakeup the event loop and call the async handle's callback.", - notes = { - [[ - It's safe to call this function from any thread. The callback will be - called on the loop thread. - ]], - }, - warnings = { - [[ - libuv will coalesce calls to `uv.async_send(async)`, that is, not - every call to it will yield an execution of the callback. For example: if - `uv.async_send()` is called 5 times in a row before the callback is called, the - callback will only be called once. If `uv.async_send()` is called again after - the callback was called, it will be called again. - ]], - }, - params = { - { name = 'async', type = 'uv_async_t' }, - { name = '...', type = 'threadargs' }, + { + name = 'listen', + method_form = 'stream:listen(backlog, callback)', + desc = [[ + Start listening for incoming connections. `backlog` indicates the number of + connections the kernel might queue, same as `listen(2)`. When a new incoming + connection is received the callback is called. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { name = 'backlog', type = 'integer' }, + cb_err(), + }, + returns = success_ret, + }, + { + name = 'accept', + method_form = 'stream:accept(client_stream)', + desc = [[ + This call is used in conjunction with `uv.listen()` to accept incoming + connections. Call this function after receiving a callback to accept the + connection. + + When the connection callback is called it is guaranteed that this function + will complete successfully the first time. If you attempt to use it more than + once, it may fail. It is suggested to only call this function once per + connection call. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { name = 'client_stream', type = 'uv_stream_t' }, + }, + returns = success_ret, + example = [[ + ```lua + server:listen(128, function (err) + local client = uv.new_tcp() + server:accept(client) + end) + ``` + ]], + }, + { + name = 'read_start', + method_form = 'stream:read_start(callback)', + desc = [[ + Read data from an incoming stream. The callback will be made several times until + there is no more data to read or `uv.read_stop()` is called. When we've reached + EOF, `data` will be `nil`. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { + name = 'callback', + type = fun({ + { 'err', opt_str }, + { 'data', opt_str }, + }), }, - returns = success_ret, }, + returns = success_ret, + example = [[ + ```lua + stream:read_start(function (err, chunk) + if err then + -- handle read error + elseif chunk then + -- handle data + else + -- handle disconnect + end + end) + ``` + ]], }, - }, - { - title = '`uv_poll_t` - Poll handle', - id = 'uv_poll_t--poll-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Poll handles are used to watch file descriptors for readability and writability, - similar to the purpose of [poll(2)](http://linux.die.net/man/2/poll). - - The purpose of poll handles is to enable integrating external libraries that - rely on the event loop to signal it about the socket status changes, like c-ares - or libssh2. Using `uv_poll_t` for any other purpose is not recommended; - `uv_tcp_t`, `uv_udp_t`, etc. provide an implementation that is faster and more - scalable than what can be achieved with `uv_poll_t`, especially on Windows. - - It is possible that poll handles occasionally signal that a file descriptor is - readable or writable even when it isn't. The user should therefore always be - prepared to handle EAGAIN or equivalent when it attempts to read from or write - to the fd. - - It is not okay to have multiple active poll handles for the same socket, this - can cause libuv to busyloop or otherwise malfunction. - - The user should not close a file descriptor while it is being polled by an - active poll handle. This can cause the handle to report an error, but it might - also start polling another socket. However the fd can be safely closed - immediately after a call to `uv.poll_stop()` or `uv.close()`. - - **Note**: On windows only sockets can be polled with poll handles. On Unix any - file descriptor that would be accepted by poll(2) can be used. - ]], - methods = { - { - name = 'new_poll', - desc = [[ - Initialize the handle using a file descriptor. + { + name = 'read_stop', + method_form = 'stream:read_stop()', + desc = [[ + Stop reading data from the stream. The read callback will no longer be called. - The file descriptor is set to non-blocking mode. - ]], - params = { - { name = 'fd', type = 'integer' }, - }, - returns = ret_or_fail('uv_poll_t', 'poll'), + This function is idempotent and may be safely called on a stopped stream. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, }, - { - name = 'new_socket_poll', - desc = [[ - Initialize the handle using a socket descriptor. On Unix this is identical to - `uv.new_poll()`. On windows it takes a SOCKET handle. + returns = success_ret, + }, + { + name = 'write', + method_form = 'stream:write(data, [callback])', + desc = [[ + Write data to stream. - The socket is set to non-blocking mode. - ]], - params = { - { name = 'fd', type = 'integer' }, - }, - returns = ret_or_fail('uv_poll_t', 'poll'), - }, - { - name = 'poll_start', - method_form = 'poll:start(events, callback)', - desc = [[ - Starts polling the file descriptor. `events` are: `"r"`, `"w"`, `"rw"`, `"d"`, - `"rd"`, `"wd"`, `"rwd"`, `"p"`, `"rp"`, `"wp"`, `"rwp"`, `"dp"`, `"rdp"`, - `"wdp"`, or `"rwdp"` where `r` is `READABLE`, `w` is `WRITABLE`, `d` is - `DISCONNECT`, and `p` is `PRIORITIZED`. As soon as an event is detected - the callback will be called with status set to 0, and the detected events set on - the events field. - - The user should not close the socket while the handle is active. If the user - does that anyway, the callback may be called reporting an error status, but this - is not guaranteed. + `data` can either be a Lua string or a table of strings. If a table is passed + in, the C backend will use writev to send all strings in a single system call. - ]], - notes = { - [[ - Calling `uv.poll_start()` on a handle that is already active is fine. - Doing so will update the events mask that is being watched for. - ]], - }, - params = { - { name = 'poll', type = 'uv_poll_t' }, - { name = 'events', type = opt('string'), default = '"rw"' }, - { - name = 'callback', - type = fun({ - { 'err', opt('string') }, - { 'events', opt('string') }, - }), - }, - }, - returns = success_ret, + The optional `callback` is for knowing when the write is complete. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { name = 'data', type = 'buffer' }, + cb_err({}, true), + }, + returns = ret_or_fail('uv_write_t', 'write'), + }, + { + name = 'write2', + method_form = 'stream:write2(data, send_handle, [callback])', + desc = [[ + Extended write function for sending handles over a pipe. The pipe must be + initialized with `ipc` option `true`. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { name = 'data', type = 'buffer' }, + { name = 'send_handle', type = 'uv_stream_t' }, + cb_err({}, true), }, - { - name = 'poll_stop', - method_form = 'poll:stop()', - desc = [[ - Stop polling the file descriptor, the callback will no longer be called. + returns = ret_or_fail('uv_write_t', 'write'), + notes = { + [[ + `send_handle` must be a TCP socket or pipe, which is a server or a + connection (listening or connected state). Bound sockets or pipes will be + assumed to be servers. ]], - params = { - { name = 'poll', type = 'uv_poll_t' }, - }, - returns = success_ret, }, }, - }, - { - title = '`uv_signal_t` - Signal handle', - id = 'uv_signal_t--signal-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Signal handles implement Unix style signal handling on a per-event loop bases. - - **Windows Notes:** - - Reception of some signals is emulated on Windows: - - SIGINT is normally delivered when the user presses CTRL+C. However, like on - Unix, it is not generated when terminal raw mode is enabled. - - SIGBREAK is delivered when the user pressed CTRL + BREAK. - - SIGHUP is generated when the user closes the console window. On SIGHUP the - program is given approximately 10 seconds to perform cleanup. After that - Windows will unconditionally terminate it. - - SIGWINCH is raised whenever libuv detects that the console has been resized. - SIGWINCH is emulated by libuv when the program uses a uv_tty_t handle to write - to the console. SIGWINCH may not always be delivered in a timely manner; libuv - will only detect size changes when the cursor is being moved. When a readable - [`uv_tty_t`][] handle is used in raw mode, resizing the console buffer will - also trigger a SIGWINCH signal. - - Watchers for other signals can be successfully created, but these signals - are never received. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV, - SIGTERM and SIGKILL. - - Calls to raise() or abort() to programmatically raise a signal are not - detected by libuv; these will not trigger a signal watcher. - - **Unix Notes:** - - - SIGKILL and SIGSTOP are impossible to catch. - - Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined - behavior. - - SIGABRT will not be caught by libuv if generated by abort(), e.g. through - assert(). - - On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads - library to manage threads. Installing watchers for those signals will lead to - unpredictable behavior and is strongly discouraged. Future versions of libuv - may simply reject them. - - ```lua - -- Create a new signal handler - local signal = uv.new_signal() - -- Define a handler function - uv.signal_start(signal, "sigint", function(signame) - print("got " .. signame .. ", shutting down") - os.exit(1) - end) - ``` - ]], - methods = { - { - name = 'new_signal', - desc = [[ - Creates and initializes a new `uv_signal_t`. Returns the Lua userdata wrapping - it. - ]], - returns = ret_or_fail('uv_signal_t', 'signal'), + { + name = 'try_write', + method_form = 'stream:try_write(data)', + desc = [[ + Same as `uv.write()`, but won't queue a write request if it can't be completed + immediately. + + Will return number of bytes written (can be less than the supplied buffer size). + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { name = 'data', type = 'buffer' }, }, - { - name = 'signal_start', - method_form = 'signal:start(signame, callback)', - desc = [[ - Start the handle with the given callback, watching for the given signal. + returns = ret_or_fail('integer', 'bytes_written'), + }, + { + name = 'try_write2', + method_form = 'stream:try_write2(data, send_handle)', + desc = [[ + Like `uv.write2()`, but with the properties of `uv.try_write()`. Not supported on Windows, where it returns `UV_EAGAIN`. - See [Constants][] for supported `signame` input and output values. - ]], - params = { - { name = 'signal', type = 'uv_signal_t' }, - { name = 'signame', type = 'string|integer' }, - { - name = 'callback', - type = fun({ { 'signame', 'string' } }), - }, - }, - returns = success_ret, + Will return number of bytes written (can be less than the supplied buffer size). + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { name = 'data', type = 'buffer' }, + { name = 'send_handle', type = 'uv_stream_t' }, }, - { - name = 'signal_start_oneshot', - method_form = 'signal:start_oneshot(signame, callback)', - desc = [[ - Same functionality as `uv.signal_start()` but the signal handler is reset the moment the signal is received. - - See [Constants][] for supported `signame` input and output values. + returns = ret_or_fail('integer', 'bytes_written'), + }, + { + name = 'is_readable', + method_form = 'stream:is_readable()', + desc = 'Returns `true` if the stream is readable, `false` otherwise.', + params = { + { name = 'stream', type = 'uv_stream_t' }, + }, + returns = 'boolean', + }, + { + name = 'is_writable', + method_form = 'stream:is_writable()', + desc = 'Returns `true` if the stream is writable, `false` otherwise.', + params = { + { name = 'stream', type = 'uv_stream_t' }, + }, + returns = 'boolean', + }, + { + name = 'stream_set_blocking', + method_form = 'stream:set_blocking(blocking)', + desc = [[ + Enable or disable blocking mode for a stream. + + When blocking mode is enabled all writes complete synchronously. The interface + remains unchanged otherwise, e.g. completion or failure of the operation will + still be reported through a callback which is made asynchronously. + ]], + params = { + { name = 'stream', type = 'uv_stream_t' }, + { name = 'blocking', type = 'boolean' }, + }, + returns = success_ret, + warnings = { + [[ + Relying too much on this API is not recommended. It is likely to + change significantly in the future. Currently this only works on Windows and + only for `uv_pipe_t` handles. Also libuv currently makes no ordering guarantee + when the blocking mode is changed after write requests have already been + submitted. Therefore it is recommended to set the blocking mode immediately + after opening or creating the stream. ]], - params = { - { name = 'signal', type = 'uv_signal_t' }, - { name = 'signame', type = 'string|integer' }, - { - name = 'callback', - type = fun({ { 'signame', 'string' } }), - }, - }, - returns = success_ret, - }, - { - name = 'signal_stop', - method_form = 'signal:stop()', - desc = 'Stop the handle, the callback will no longer be called.', - params = { - { name = 'signal', type = 'uv_signal_t' }, - }, - returns = success_ret, }, }, + { + name = 'stream_get_write_queue_size', + method_form = 'stream:get_write_queue_size()', + desc = "Returns the stream's write queue size.", + params = { + { name = 'stream', type = 'uv_stream_t' }, + }, + returns = 'integer', + }, }, - { - title = '`uv_process_t` - Process handle', - id = 'uv_process_t--process-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Process handles will spawn a new process and allow the user to control it and - establish communication channels with it using streams. - ]], - methods = { - { - name = 'disable_stdio_inheritance', - desc = [[ - Disables inheritance for file descriptors / handles that this process inherited - from its parent. The effect is that child processes spawned by this process - don't accidentally inherit these handles. - - It is recommended to call this function as early in your program as possible, - before the inherited file descriptors can be closed or duplicated. - ]], - notes = { - [[ - This function works on a best-effort basis: there is no guarantee that - libuv can discover all file descriptors that were inherited. In general it does - a better job on Windows than it does on Unix. - ]], - }, + }, + { + title = '`uv_tcp_t` - TCP handle', + id = 'uv_tcp_t--tcp-handle', + class = 'uv_tcp_t', + desc = [[ + > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. + + TCP handles are used to represent both TCP streams and servers. + ]], + funcs = { + { + name = 'new_tcp', + desc = [[ + Creates and initializes a new `uv_tcp_t`. Returns the Lua userdata wrapping it. + + If set, `flags` must be a valid address family. See [Constants][] for supported + address family input values. + ]], + params = { + { name = 'flags', type = opt(union('string', 'integer')) }, }, - { - name = 'spawn', - desc = [[ - Initializes the process handle and starts the process. If the process is - successfully spawned, this function will return the handle and pid of the child - process. - - Possible reasons for failing to spawn would include (but not be limited to) the - file to execute not existing, not having permissions to use the setuid or setgid - specified, or not having enough memory to allocate for the new process. - - ```lua - local stdin = uv.new_pipe() - local stdout = uv.new_pipe() - local stderr = uv.new_pipe() - - print("stdin", stdin) - print("stdout", stdout) - print("stderr", stderr) - - local handle, pid = uv.spawn("cat", { - stdio = {stdin, stdout, stderr} - }, function(code, signal) -- on exit - print("exit code", code) - print("exit signal", signal) - end) - - print("process opened", handle, pid) - - uv.read_start(stdout, function(err, data) - assert(not err, err) - if data then - print("stdout chunk", stdout, data) - else - print("stdout end", stdout) - end - end) - - uv.read_start(stderr, function(err, data) - assert(not err, err) - if data then - print("stderr chunk", stderr, data) - else - print("stderr end", stderr) - end - end) - - uv.write(stdin, "Hello World") - - uv.shutdown(stdin, function() - print("stdin shutdown", stdin) - uv.close(handle, function() - print("process closed", handle, pid) - end) - end) - ``` - - The `options` table accepts the following fields: - - - `options.args` - Command line arguments as a list of strings. The first - string should *not* be the path to the program, since that is already - provided via `path`. On Windows, this uses CreateProcess which concatenates - the arguments into a string. This can cause some strange errors - (see `options.verbatim` below for Windows). - - `options.stdio` - Set the file descriptors that will be made available to - the child process. The convention is that the first entries are stdin, stdout, - and stderr. (**Note**: On Windows, file descriptors after the third are - available to the child process only if the child processes uses the MSVCRT - runtime.) - - `options.env` - Set environment variables for the new process. - - `options.cwd` - Set the current working directory for the sub-process. - - `options.uid` - Set the child process' user id. - - `options.gid` - Set the child process' group id. - - `options.verbatim` - If true, do not wrap any arguments in quotes, or - perform any other escaping, when converting the argument list into a command - line string. This option is only meaningful on Windows systems. On Unix it is - silently ignored. - - `options.detached` - If true, spawn the child process in a detached state - - this will make it a process group leader, and will effectively enable the - child to keep running after the parent exits. Note that the child process - will still keep the parent's event loop alive unless the parent process calls - `uv.unref()` on the child's process handle. - - `options.hide` - If true, hide the subprocess console window that would - normally be created. This option is only meaningful on Windows systems. On - Unix it is silently ignored. - - The `options.stdio` entries can take many shapes. - - - If they are numbers, then the child process inherits that same zero-indexed - fd from the parent process. - - If `uv_stream_t` handles are passed in, those are used as a read-write pipe - or inherited stream depending if the stream has a valid fd. - - Including `nil` placeholders means to ignore that fd in the child process. - - When the child process exits, `on_exit` is called with an exit code and signal. + returns = ret_or_fail('uv_tcp_t', 'tcp'), + }, + { + name = 'tcp_open', + method_form = 'tcp:open(sock)', + desc = 'Open an existing file descriptor or SOCKET as a TCP handle.', + params = { + { name = 'tcp', type = 'uv_tcp_t' }, + { name = 'sock', type = 'integer' }, + }, + returns = success_ret, + notes = { + [[ + The passed file descriptor or SOCKET is not checked for its type, but it's required that it represents a valid stream socket. ]], - params = { - { name = 'path', type = 'string' }, - { name = 'options', type = 'table', desc = '(see below)' }, - { - name = 'on_exit', - type = fun({ { 'code', 'integer' }, { 'signal', 'integer' } }), - }, - }, - returns = { - { 'uv_process_t', 'handle' }, - { 'integer', 'pid' }, - }, }, - { - name = 'process_kill', - method_form = 'process:kill(signame)', - desc = [[ - Sends the specified signal to the given process handle. Check the documentation - on `uv_signal_t` for signal support, specially on Windows. + }, + { + name = 'tcp_nodelay', + method_form = 'tcp:nodelay(enable)', + desc = "Enable / disable Nagle's algorithm.", + params = { + { name = 'tcp', type = 'uv_tcp_t' }, + { name = 'enable', type = 'boolean' }, + }, + returns = success_ret, + }, + { + name = 'tcp_keepalive', + method_form = 'tcp:keepalive(enable, [delay])', + desc = [[ + Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, + ignored when enable is `false`. + ]], + params = { + { name = 'tcp', type = 'uv_tcp_t' }, + { name = 'enable', type = 'boolean' }, + { name = 'delay', type = opt_int }, + }, + returns = success_ret, + }, + { + name = 'tcp_simultaneous_accepts', + method_form = 'tcp:simultaneous_accepts(enable)', + desc = [[ + Enable / disable simultaneous asynchronous accept requests that are queued by + the operating system when listening for new TCP connections. + + This setting is used to tune a TCP server for the desired performance. Having + simultaneous accepts can significantly improve the rate of accepting connections + (which is why it is enabled by default) but may lead to uneven load distribution + in multi-process setups. + ]], + params = { + { name = 'tcp', type = 'uv_tcp_t' }, + { name = 'enable', type = 'boolean' }, + }, + returns = success_ret, + }, + { + name = 'tcp_bind', + method_form = 'tcp:bind(host, port, [flags])', + desc = [[ + Bind the handle to an host and port. `host` should be an IP address and + not a domain name. Any `flags` are set with a table with field `ipv6only` + equal to `true` or `false`. + + When the port is already taken, you can expect to see an `EADDRINUSE` error + from either `uv.tcp_bind()`, `uv.listen()` or `uv.tcp_connect()`. That is, a + successful call to this function does not guarantee that the call to `uv.listen()` + or `uv.tcp_connect()` will succeed as well. + + Use a port of `0` to let the OS assign an ephemeral port. You can look it up + later using `uv.tcp_getsockname()`. + ]], + params = { + { name = 'tcp', type = 'uv_tcp_t' }, + { name = 'host', type = 'string' }, + { name = 'port', type = 'integer' }, + { + name = 'flags', + type = opt(table({ + { 'ipv6only', 'boolean' }, + })), + }, + }, + returns = success_ret, + }, + { + name = 'tcp_getpeername', + method_form = 'tcp:getpeername()', + desc = [[ + Get the address of the peer connected to the handle. - See [Constants][] for supported `signame` input values. - ]], - params = { - { name = 'process', type = 'uv_process_t' }, - { name = 'signame', type = opt(union('string', 'integer')), default = 'sigterm' }, - }, - returns = success_ret, + See [Constants][] for supported address `family` output values. + ]], + params = { + { name = 'tcp', type = 'uv_tcp_t' }, }, - { - name = 'kill', - desc = [[ - Sends the specified signal to the given PID. Check the documentation on - `uv_signal_t` for signal support, specially on Windows. + returns = ret_or_fail('socketinfo', 'address'), + }, + { + name = 'tcp_getsockname', + method_form = 'tcp:getsockname()', + desc = [[ + Get the current address to which the handle is bound. - See [Constants][] for supported `signame` input values. - ]], - params = { - { name = 'pid', type = 'integer' }, - { name = 'signame', type = opt(union('string', 'integer')), default = 'sigterm' }, - }, - returns = success_ret, - }, - { - name = 'process_get_pid', - method_form = 'process:get_pid()', - desc = "Returns the handle's pid.", - params = { - { name = 'process', type = 'uv_process_t' }, - }, - returns = 'integer', + See [Constants][] for supported address `family` output values. + ]], + params = { + { name = 'tcp', type = 'uv_tcp_t' }, }, + returns = ret_or_fail('socketinfo', 'address'), }, - }, - { - title = '`uv_stream_t` - Stream handle', - id = 'uv_stream_t--stream-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - Stream handles provide an abstraction of a duplex communication channel. - [`uv_stream_t`][] is an abstract type, libuv provides 3 stream implementations - in the form of [`uv_tcp_t`][], [`uv_pipe_t`][] and [`uv_tty_t`][]. - ]], - methods = { - { - name = 'shutdown', - method_form = 'stream:shutdown([callback])', - desc = [[ - Shutdown the outgoing (write) side of a duplex stream. It waits for pending - write requests to complete. The callback is called after shutdown is complete. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { - name = 'callback', - type = opt(fun({ - { 'err', opt('string') }, - })), - }, - }, - returns = ret_or_fail('uv_shutdown_t', 'shutdown'), - }, - { - name = 'listen', - method_form = 'stream:listen(backlog, callback)', - desc = [[ - Start listening for incoming connections. `backlog` indicates the number of - connections the kernel might queue, same as `listen(2)`. When a new incoming - connection is received the callback is called. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { name = 'backlog', type = 'integer' }, - cb_err(), - }, - returns = success_ret, - }, - { - name = 'accept', - method_form = 'stream:accept(client_stream)', - desc = [[ - This call is used in conjunction with `uv.listen()` to accept incoming - connections. Call this function after receiving a callback to accept the - connection. - - When the connection callback is called it is guaranteed that this function - will complete successfully the first time. If you attempt to use it more than - once, it may fail. It is suggested to only call this function once per - connection call. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { name = 'client_stream', type = 'uv_stream_t' }, - }, - returns = success_ret, - example = [[ - ```lua - server:listen(128, function (err) - local client = uv.new_tcp() - server:accept(client) - end) - ``` - ]], + { + name = 'tcp_connect', + method_form = 'tcp:connect(host, port, callback)', + desc = 'Establish an IPv4 or IPv6 TCP connection.', + params = { + { name = 'tcp', type = 'uv_tcp_t' }, + { name = 'host', type = 'string' }, + { name = 'port', type = 'integer' }, + cb_err(), + }, + returns = ret_or_fail('uv_connect_t', 'connect'), + example = [[ + ```lua + local client = uv.new_tcp() + client:connect("127.0.0.1", 8080, function (err) + -- check error and carry on. + end) + ``` + ]], + }, + { + name = 'tcp_write_queue_size', + method_form = 'tcp:write_queue_size()', + deprecated = 'Please use `uv.stream_get_write_queue_size()` instead.', + params = { + { name = 'tcp', type = 'uv_tcp_t' }, }, - { - name = 'read_start', - method_form = 'stream:read_start(callback)', - desc = [[ - Read data from an incoming stream. The callback will be made several times until - there is no more data to read or `uv.read_stop()` is called. When we've reached - EOF, `data` will be `nil`. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { - name = 'callback', - type = fun({ - { 'err', opt('string') }, - { 'data', opt('string') }, - }), - }, - }, - returns = success_ret, - example = [[ - ```lua - stream:read_start(function (err, chunk) - if err then - -- handle read error - elseif chunk then - -- handle data - else - -- handle disconnect - end - end) - ``` - ]], + }, + { + name = 'tcp_close_reset', + method_form = 'tcp:close_reset([callback])', + desc = [[ + Resets a TCP connection by sending a RST packet. This is accomplished by setting + the SO_LINGER socket option with a linger interval of zero and then calling + `uv.close()`. Due to some platform inconsistencies, mixing of `uv.shutdown()` + and `uv.tcp_close_reset()` calls is not allowed. + ]], + params = { + { name = 'tcp', type = 'uv_tcp_t' }, + cb(nil, true), }, - { - name = 'read_stop', - method_form = 'stream:read_stop()', - desc = [[ - Stop reading data from the stream. The read callback will no longer be called. + returns = success_ret, + }, + { + name = 'socketpair', + desc = [[ + Create a pair of connected sockets with the specified properties. The resulting handles can be passed to `uv.tcp_open`, used with `uv.spawn`, or for any other purpose. - This function is idempotent and may be safely called on a stopped stream. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - }, - returns = success_ret, - }, - { - name = 'write', - method_form = 'stream:write(data, [callback])', - desc = [[ - Write data to stream. + See [Constants][] for supported `socktype` input values. - `data` can either be a Lua string or a table of strings. If a table is passed - in, the C backend will use writev to send all strings in a single system call. + When `protocol` is set to 0 or nil, it will be automatically chosen based on the socket's domain and type. When `protocol` is specified as a string, it will be looked up using the `getprotobyname(3)` function (examples: `"ip"`, `"icmp"`, `"tcp"`, `"udp"`, etc). - The optional `callback` is for knowing when the write is complete. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { name = 'data', type = 'buffer' }, - cb_err({}, true), - }, - returns = ret_or_fail('uv_write_t', 'write'), - }, - { - name = 'write2', - method_form = 'stream:write2(data, send_handle, [callback])', - desc = [[ - Extended write function for sending handles over a pipe. The pipe must be - initialized with `ipc` option `true`. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { name = 'data', type = 'buffer' }, - { name = 'send_handle', type = 'uv_stream_t' }, - cb_err({}, true), + Flags: + - `nonblock`: Opens the specified socket handle for `OVERLAPPED` or `FIONBIO`/`O_NONBLOCK` I/O usage. This is recommended for handles that will be used by libuv, and not usually recommended otherwise. + + Equivalent to `socketpair(2)` with a domain of `AF_UNIX`. + ]], + params = { + { name = 'socktype', type = opt(union('string', 'integer')), default = 'stream' }, + { name = 'protocol', type = opt(union('string', 'integer')), default = '0' }, + { + name = 'flags1', + type = opt(table({ { 'nonblock', 'boolean', 'false' } })), }, - returns = ret_or_fail('uv_write_t', 'write'), - notes = { - [[ - `send_handle` must be a TCP socket or pipe, which is a server or a - connection (listening or connected state). Bound sockets or pipes will be - assumed to be servers. - ]], + { + name = 'flags2', + type = opt(table({ { 'nonblock', 'boolean', 'false' } })), }, }, - { - name = 'try_write', - method_form = 'stream:try_write(data)', - desc = [[ - Same as `uv.write()`, but won't queue a write request if it can't be completed - immediately. - - Will return number of bytes written (can be less than the supplied buffer size). - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { name = 'data', type = 'buffer' }, - }, - returns = ret_or_fail('integer', 'bytes_written'), + returns = { + { opt('[integer, integer]'), 'fds' }, + { opt_str, 'err' }, + { opt('uv.error_name'), 'err_name' }, }, - { - name = 'try_write2', - method_form = 'stream:try_write2(data, send_handle)', - desc = [[ - Like `uv.write2()`, but with the properties of `uv.try_write()`. Not supported on Windows, where it returns `UV_EAGAIN`. + example = [[ + ```lua + -- Simple read/write with tcp + local fds = uv.socketpair(nil, nil, {nonblock=true}, {nonblock=true}) - Will return number of bytes written (can be less than the supplied buffer size). - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { name = 'data', type = 'buffer' }, - { name = 'send_handle', type = 'uv_stream_t' }, - }, - returns = ret_or_fail('integer', 'bytes_written'), - }, - { - name = 'is_readable', - method_form = 'stream:is_readable()', - desc = 'Returns `true` if the stream is readable, `false` otherwise.', - params = { - { name = 'stream', type = 'uv_stream_t' }, - }, - returns = 'boolean', - }, - { - name = 'is_writable', - method_form = 'stream:is_writable()', - desc = 'Returns `true` if the stream is writable, `false` otherwise.', - params = { - { name = 'stream', type = 'uv_stream_t' }, - }, - returns = 'boolean', - }, - { - name = 'stream_set_blocking', - method_form = 'stream:set_blocking(blocking)', - desc = [[ - Enable or disable blocking mode for a stream. + local sock1 = uv.new_tcp() + sock1:open(fds[1]) - When blocking mode is enabled all writes complete synchronously. The interface - remains unchanged otherwise, e.g. completion or failure of the operation will - still be reported through a callback which is made asynchronously. - ]], - params = { - { name = 'stream', type = 'uv_stream_t' }, - { name = 'blocking', type = 'boolean' }, - }, - returns = success_ret, - warnings = { - [[ - Relying too much on this API is not recommended. It is likely to - change significantly in the future. Currently this only works on Windows and - only for `uv_pipe_t` handles. Also libuv currently makes no ordering guarantee - when the blocking mode is changed after write requests have already been - submitted. Therefore it is recommended to set the blocking mode immediately - after opening or creating the stream. - ]], - }, + local sock2 = uv.new_tcp() + sock2:open(fds[2]) + + sock1:write("hello") + sock2:read_start(function(err, chunk) + assert(not err, err) + print(chunk) + end) + ``` + ]], + }, + }, + }, + { + title = '`uv_pipe_t` - Pipe handle', + id = 'uv_pipe_t--pipe-handle', + class = 'uv_pipe_t', + desc = [[ + > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. + + Pipe handles provide an abstraction over local domain sockets on Unix and named pipes on Windows. + + ```lua + local pipe = uv.new_pipe(false) + + pipe:bind('/tmp/sock.test') + + pipe:listen(128, function() + local client = uv.new_pipe(false) + pipe:accept(client) + client:write("hello!\n") + client:close() + end) + ``` + ]], + funcs = { + { + name = 'new_pipe', + desc = [[ + Creates and initializes a new `uv_pipe_t`. Returns the Lua userdata wrapping + it. The `ipc` argument is a boolean to indicate if this pipe will be used for + handle passing between processes. + ]], + params = { + { name = 'ipc', type = opt_bool, default = 'false' }, + }, + returns = ret_or_fail('uv_pipe_t', 'pipe'), + }, + { + name = 'pipe_open', + method_form = 'pipe:open(fd)', + desc = [[ + Open an existing file descriptor or [`uv_handle_t`][] as a pipe. + ]], + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + { name = 'fd', type = 'integer' }, }, - { - name = 'stream_get_write_queue_size', - method_form = 'stream:get_write_queue_size()', - desc = "Returns the stream's write queue size.", - returns = 'integer', + returns = success_ret, + notes = { + 'The file descriptor is set to non-blocking mode.', }, }, - }, - { - title = '`uv_tcp_t` - TCP handle', - id = 'uv_tcp_t--tcp-handle', - desc = [[ - > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. - - TCP handles are used to represent both TCP streams and servers. - ]], - methods = { - { - name = 'new_tcp', - desc = [[ - Creates and initializes a new `uv_tcp_t`. Returns the Lua userdata wrapping it. - - If set, `flags` must be a valid address family. See [Constants][] for supported - address family input values. - ]], - params = { - { name = 'flags', type = opt(union('string', 'integer')) }, - }, - returns = ret_or_fail('uv_tcp_t', 'tcp'), - }, - { - name = 'tcp_open', - method_form = 'tcp:open(sock)', - desc = 'Open an existing file descriptor or SOCKET as a TCP handle.', - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - { name = 'sock', type = 'integer' }, - }, - returns = success_ret, - notes = { - [[ - The passed file descriptor or SOCKET is not checked for its type, but it's required that it represents a valid stream socket. - ]], - }, + { + name = 'pipe_bind', + method_form = 'pipe:bind(name)', + desc = 'Bind the pipe to a file path (Unix) or a name (Windows).', + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + { name = 'name', type = 'string' }, }, - { - name = 'tcp_nodelay', - method_form = 'tcp:nodelay(enable)', - desc = "Enable / disable Nagle's algorithm.", - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - { name = 'enable', type = 'boolean' }, - }, - returns = success_ret, - }, - { - name = 'tcp_keepalive', - method_form = 'tcp:keepalive(enable, [delay])', - desc = [[ - Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, - ignored when enable is `false`. - ]], - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - { name = 'enable', type = 'boolean' }, - { name = 'delay', type = opt('integer') }, - }, - returns = success_ret, - }, - { - name = 'tcp_simultaneous_accepts', - method_form = 'tcp:simultaneous_accepts(enable)', - desc = [[ - Enable / disable simultaneous asynchronous accept requests that are queued by - the operating system when listening for new TCP connections. - - This setting is used to tune a TCP server for the desired performance. Having - simultaneous accepts can significantly improve the rate of accepting connections - (which is why it is enabled by default) but may lead to uneven load distribution - in multi-process setups. + returns = success_ret, + notes = { + [[ + Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, + typically between 92 and 108 bytes. ]], - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - { name = 'enable', type = 'boolean' }, - }, - returns = success_ret, - }, - { - name = 'tcp_bind', - method_form = 'tcp:bind(host, port, [flags])', - desc = [[ - Bind the handle to an host and port. `host` should be an IP address and - not a domain name. Any `flags` are set with a table with field `ipv6only` - equal to `true` or `false`. - - When the port is already taken, you can expect to see an `EADDRINUSE` error - from either `uv.tcp_bind()`, `uv.listen()` or `uv.tcp_connect()`. That is, a - successful call to this function does not guarantee that the call to `uv.listen()` - or `uv.tcp_connect()` will succeed as well. - - Use a port of `0` to let the OS assign an ephemeral port. You can look it up - later using `uv.tcp_getsockname()`. - ]], - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - { name = 'host', type = 'string' }, - { name = 'port', type = 'integer' }, - { - name = 'flags', - type = opt(table({ - { 'ipv6only', 'boolean' }, - })), - }, - }, - returns = success_ret, }, - { - name = 'tcp_getpeername', - method_form = 'tcp:getpeername()', - desc = [[ - Get the address of the peer connected to the handle. - - See [Constants][] for supported address `family` output values. + }, + { + name = 'pipe_connect', + method_form = 'pipe:connect(name, [callback])', + desc = 'Connect to the Unix domain socket or the named pipe.', + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + { name = 'name', type = 'string' }, + cb_err({}, true), + }, + returns = ret_or_fail('uv_connect_t', 'connect'), + notes = { + [[ + Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, + typically between 92 and 108 bytes. ]], - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - }, - returns = ret_or_fail('socketinfo', 'address'), }, - { - name = 'tcp_getsockname', - method_form = 'tcp:getsockname()', - desc = [[ - Get the current address to which the handle is bound. - - See [Constants][] for supported address `family` output values. - ]], - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - }, - returns = ret_or_fail('socketinfo', 'address'), - }, - { - name = 'tcp_connect', - method_form = 'tcp:connect(host, port, callback)', - desc = 'Establish an IPv4 or IPv6 TCP connection.', - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - { name = 'host', type = 'string' }, - { name = 'port', type = 'integer' }, - cb_err(), - }, - returns = ret_or_fail('uv_connect_t', 'connect'), - example = [[ - ```lua - local client = uv.new_tcp() - client:connect("127.0.0.1", 8080, function (err) - -- check error and carry on. - end) - ``` - ]], + }, + { + name = 'pipe_getsockname', + method_form = 'pipe:getsockname()', + desc = 'Get the name of the Unix domain socket or the named pipe.', + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + }, + returns = ret_or_fail('string', 'name'), + }, + { + name = 'pipe_getpeername', + method_form = 'pipe:getpeername()', + desc = [[ + Get the name of the Unix domain socket or the named pipe to which the handle is + connected. + ]], + params = { + { name = 'pipe', type = 'uv_pipe_t' }, }, - { - name = 'tcp_write_queue_size', - method_form = 'tcp:write_queue_size()', - deprecated = 'Please use `uv.stream_get_write_queue_size()` instead.', - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - }, + returns = ret_or_fail('string', 'name'), + }, + { + name = 'pipe_pending_instances', + method_form = 'pipe:pending_instances(count)', + desc = [[ + Set the number of pending pipe instance handles when the pipe server is waiting + for connections. + ]], + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + { name = 'count', type = 'integer' }, }, - { - name = 'tcp_close_reset', - method_form = 'tcp:close_reset([callback])', - desc = [[ - Resets a TCP connection by sending a RST packet. This is accomplished by setting - the SO_LINGER socket option with a linger interval of zero and then calling - `uv.close()`. Due to some platform inconsistencies, mixing of `uv.shutdown()` - and `uv.tcp_close_reset()` calls is not allowed. - ]], - params = { - { name = 'tcp', type = 'uv_tcp_t' }, - cb(nil, true), - }, - returns = success_ret, + notes = { + 'This setting applies to Windows only.', }, - { - name = 'socketpair', - desc = [[ - Create a pair of connected sockets with the specified properties. The resulting handles can be passed to `uv.tcp_open`, used with `uv.spawn`, or for any other purpose. - - See [Constants][] for supported `socktype` input values. - - When `protocol` is set to 0 or nil, it will be automatically chosen based on the socket's domain and type. When `protocol` is specified as a string, it will be looked up using the `getprotobyname(3)` function (examples: `"ip"`, `"icmp"`, `"tcp"`, `"udp"`, etc). + }, + { + name = 'pipe_pending_count', + method_form = 'pipe:pending_count()', + desc = 'Returns the pending pipe count for the named pipe.', + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + }, + returns = 'integer', + }, + { + name = 'pipe_pending_type', + method_form = 'pipe:pending_type()', + desc = [[ + Used to receive handles over IPC pipes. + + First - call `uv.pipe_pending_count()`, if it's > 0 then initialize a handle of + the given type, returned by `uv.pipe_pending_type()` and call + `uv.accept(pipe, handle)`. + ]], + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + }, + returns = 'string', + }, + { + name = 'pipe_chmod', + method_form = 'pipe:chmod(flags)', + desc = [[ + Alters pipe permissions, allowing it to be accessed from processes run by different users. + Makes the pipe writable or readable by all users. `flags` are: `"r"`, `"w"`, `"rw"`, or `"wr"` + where `r` is `READABLE` and `w` is `WRITABLE`. This function is blocking. + ]], + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + { name = 'flags', type = 'string' }, + }, + returns = success_ret, + }, + { + name = 'pipe', + desc = [[ + Create a pair of connected pipe handles. Data may be written to the `write` fd and read from the `read` fd. The resulting handles can be passed to `pipe_open`, used with `spawn`, or for any other purpose. - Flags: - - `nonblock`: Opens the specified socket handle for `OVERLAPPED` or `FIONBIO`/`O_NONBLOCK` I/O usage. This is recommended for handles that will be used by libuv, and not usually recommended otherwise. + Flags: + - `nonblock`: Opens the specified socket handle for `OVERLAPPED` or `FIONBIO`/`O_NONBLOCK` I/O usage. This is recommended for handles that will be used by libuv, and not usually recommended otherwise. - Equivalent to `socketpair(2)` with a domain of `AF_UNIX`. - ]], - params = { - { name = 'socktype', type = opt(union('string', 'integer')), default = 'stream' }, - { name = 'protocol', type = opt(union('string', 'integer')), default = '0' }, - { - name = 'flags1', - type = opt(table({ { 'nonblock', 'boolean', 'false' } })), - }, - { - name = 'flags2', - type = opt(table({ { 'nonblock', 'boolean', 'false' } })), - }, - }, - returns = { - { opt('[integer, integer]'), 'fds' }, - { opt('string'), 'err' }, - { opt('string'), 'err_name' }, - }, - example = [[ - ```lua - -- Simple read/write with tcp - local fds = uv.socketpair(nil, nil, {nonblock=true}, {nonblock=true}) + Equivalent to `pipe(2)` with the `O_CLOEXEC` flag set. + ]], + params = { + { + name = 'read_flags', + type = opt(table({ { 'nonblock', 'boolean', 'false' } })), + }, + { + name = 'write_flags', + type = opt(table({ { 'nonblock', 'boolean', 'false' } })), + }, + }, + returns = ret_or_fail( + table({ + { 'read', 'integer', nil, '(file descriptor)' }, + { 'write', 'integer', nil, '(file descriptor)' }, + }), + 'fds' + ), + example = [[ + ```lua + -- Simple read/write with pipe_open + local fds = uv.pipe({nonblock=true}, {nonblock=true}) + + local read_pipe = uv.new_pipe() + read_pipe:open(fds.read) + + local write_pipe = uv.new_pipe() + write_pipe:open(fds.write) + + write_pipe:write("hello") + read_pipe:read_start(function(err, chunk) + assert(not err, err) + print(chunk) + end) + ``` + ]], + }, + { + name = 'pipe_bind2', + method_form = 'pipe:bind2(name, [flags])', + desc = [[ + Bind the pipe to a file path (Unix) or a name (Windows). - local sock1 = uv.new_tcp() - sock1:open(fds[1]) + `Flags`: - local sock2 = uv.new_tcp() - sock2:open(fds[2]) + - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. + - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. + - If `type(flags)` is `nil`, it use default value `0`. + - Returns `EINVAL` for unsupported flags without performing the bind operation. - sock1:write("hello") - sock2:read_start(function(err, chunk) - assert(not err, err) - print(chunk) - end) - ``` + Supports Linux abstract namespace sockets. namelen must include the leading '\0' byte but not the trailing nul byte. + ]], + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + { name = 'name', type = 'string' }, + { name = 'flags', type = opt(union('integer', 'table')), default = '0' }, + }, + returns = success_ret, + notes = { + [[ + 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, + typically between 92 and 108 bytes. + 2. New in version 1.46.0. ]], }, }, - }, - { - title = '`uv_pipe_t` - Pipe handle', - id = 'uv_pipe_t--pipe-handle', - desc = [[ - > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. + { + name = 'pipe_connect2', + method_form = 'pipe:connect2(name, [flags], [callback])', + desc = [[ + Connect to the Unix domain socket or the named pipe. - Pipe handles provide an abstraction over local domain sockets on Unix and named pipes on Windows. + `Flags`: - ```lua - local pipe = uv.new_pipe(false) + - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. + - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. + - If `type(flags)` is `nil`, it use default value `0`. + - Returns `EINVAL` for unsupported flags without performing the bind operation. - pipe:bind('/tmp/sock.test') - - pipe:listen(128, function() - local client = uv.new_pipe(false) - pipe:accept(client) - client:write("hello!\n") - client:close() - end) - ``` - ]], - methods = { - { - name = 'new_pipe', - desc = [[ - Creates and initializes a new `uv_pipe_t`. Returns the Lua userdata wrapping - it. The `ipc` argument is a boolean to indicate if this pipe will be used for - handle passing between processes. - ]], - params = { - { name = 'ipc', type = opt('boolean'), default = 'false' }, - }, - returns = ret_or_fail('uv_pipe_t', 'pipe'), + Supports Linux abstract namespace sockets. namelen must include the leading nul byte but not the trailing nul byte. + ]], + params = { + { name = 'pipe', type = 'uv_pipe_t' }, + { name = 'name', type = 'string' }, + { name = 'flags', type = opt(union('integer', 'table')), default = '0' }, + cb_err({}, true), }, - { - name = 'pipe_open', - method_form = 'pipe:open(fd)', - desc = [[ - Open an existing file descriptor or [`uv_handle_t`][] as a pipe. + returns = ret_or_fail('uv_connect_t', 'connect'), + notes = { + [[ + 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, + typically between 92 and 108 bytes. + 2. New in version 1.46.0. ]], - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - { name = 'fd', type = 'integer' }, - }, - returns = success_ret, - notes = { - 'The file descriptor is set to non-blocking mode.', - }, }, - { - name = 'pipe_bind', - method_form = 'pipe:bind(name)', - desc = 'Bind the pipe to a file path (Unix) or a name (Windows).', - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - { name = 'name', type = 'string' }, - }, - returns = success_ret, - notes = { - [[ - Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, - typically between 92 and 108 bytes. - ]], - }, + }, + }, + }, + { + title = '`uv_tty_t` - TTY handle', + id = 'uv_tty_t--tty-handle', + class = 'uv_tty_t', + desc = [[ + > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. + + TTY handles represent a stream for the console. + + ```lua + -- Simple echo program + local stdin = uv.new_tty(0, true) + local stdout = uv.new_tty(1, false) + + stdin:read_start(function (err, data) + assert(not err, err) + if data then + stdout:write(data) + else + stdin:close() + stdout:close() + end + end) + ``` + ]], + funcs = { + { + name = 'new_tty', + desc = [[ + Initialize a new TTY stream with the given file descriptor. Usually the file + descriptor will be: + + - 0 - stdin + - 1 - stdout + - 2 - stderr + + On Unix this function will determine the path of the fd of the terminal using + ttyname_r(3), open it, and use it if the passed file descriptor refers to a TTY. + This lets libuv put the tty in non-blocking mode without affecting other + processes that share the tty. + + This function is not thread safe on systems that don’t support ioctl TIOCGPTN or TIOCPTYGNAME, for instance OpenBSD and Solaris. + ]], + params = { + { name = 'fd', type = 'integer' }, + { name = 'readable', type = 'boolean' }, }, - { - name = 'pipe_connect', - method_form = 'pipe:connect(name, [callback])', - desc = 'Connect to the Unix domain socket or the named pipe.', - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - { name = 'name', type = 'string' }, - cb_err({}, true), - }, - returns = ret_or_fail('uv_connect_t', 'connect'), - notes = { - [[ - Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, - typically between 92 and 108 bytes. - ]], - }, + returns = ret_or_fail('uv_tty_t', 'tty'), + notes = { + 'If reopening the TTY fails, libuv falls back to blocking writes.', }, - { - name = 'pipe_getsockname', - method_form = 'pipe:getsockname()', - desc = 'Get the name of the Unix domain socket or the named pipe.', - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - }, - returns = ret_or_fail('string', 'name'), - }, - { - name = 'pipe_getpeername', - method_form = 'pipe:getpeername()', - desc = [[ - Get the name of the Unix domain socket or the named pipe to which the handle is - connected. - ]], - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - }, - returns = ret_or_fail('string', 'name'), - }, - { - name = 'pipe_pending_instances', - method_form = 'pipe:pending_instances(count)', - desc = [[ - Set the number of pending pipe instance handles when the pipe server is waiting - for connections. - ]], - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - { name = 'count', type = 'integer' }, - }, - notes = { - 'This setting applies to Windows only.', - }, + }, + { + name = 'tty_set_mode', + method_form = 'tty:set_mode(mode)', + desc = [[ + Set the TTY using the specified terminal mode. + + See [Constants][] for supported TTY mode input values. + ]], + params = { + { name = 'tty', type = 'uv_tty_t' }, + { name = 'mode', type = 'string|integer' }, }, - { - name = 'pipe_pending_count', - method_form = 'pipe:pending_count()', - desc = 'Returns the pending pipe count for the named pipe.', - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - }, - returns = 'integer', + returns = success_ret, + }, + { + name = 'tty_reset_mode', + desc = [[ + To be called when the program exits. Resets TTY settings to default values for + the next process to take over. + + This function is async signal-safe on Unix platforms but can fail with error + code `EBUSY` if you call it when execution is inside `uv.tty_set_mode()`. + ]], + returns = success_ret, + }, + { + name = 'tty_get_winsize', + method_form = 'tty:get_winsize()', + desc = 'Gets the current Window width and height.', + params = { + { name = 'tty', type = 'uv_tty_t' }, + }, + returns_doc = '`integer, integer` or `fail`', + returns = { + { opt_int, 'width' }, + { union('integer', 'string'), 'height or err' }, + { opt('uv.error_name'), 'err_name' }, }, - { - name = 'pipe_pending_type', - method_form = 'pipe:pending_type()', - desc = [[ - Used to receive handles over IPC pipes. - - First - call `uv.pipe_pending_count()`, if it's > 0 then initialize a handle of - the given type, returned by `uv.pipe_pending_type()` and call - `uv.accept(pipe, handle)`. - ]], - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - }, - returns = 'string', - }, - { - name = 'pipe_chmod', - method_form = 'pipe:chmod(flags)', - desc = [[ - Alters pipe permissions, allowing it to be accessed from processes run by different users. - Makes the pipe writable or readable by all users. `flags` are: `"r"`, `"w"`, `"rw"`, or `"wr"` - where `r` is `READABLE` and `w` is `WRITABLE`. This function is blocking. - ]], - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - { name = 'flags', type = 'string' }, - }, - returns = success_ret, + }, + { + name = 'tty_set_vterm_state', + desc = [[ + Controls whether console virtual terminal sequences are processed by libuv or + console. Useful in particular for enabling ConEmu support of ANSI X3.64 and + Xterm 256 colors. Otherwise Windows10 consoles are usually detected + automatically. State should be one of: `"supported"` or `"unsupported"`. + + This function is only meaningful on Windows systems. On Unix it is silently + ignored. + ]], + params = { + { name = 'state', type = 'string' }, }, - { - name = 'pipe', - desc = [[ - Create a pair of connected pipe handles. Data may be written to the `write` fd and read from the `read` fd. The resulting handles can be passed to `pipe_open`, used with `spawn`, or for any other purpose. - - Flags: - - `nonblock`: Opens the specified socket handle for `OVERLAPPED` or `FIONBIO`/`O_NONBLOCK` I/O usage. This is recommended for handles that will be used by libuv, and not usually recommended otherwise. + }, + { + name = 'tty_get_vterm_state', + desc = [[ + Get the current state of whether console virtual terminal sequences are handled + by libuv or the console. The return value is `"supported"` or `"unsupported"`. - Equivalent to `pipe(2)` with the `O_CLOEXEC` flag set. - ]], - params = { - { - name = 'read_flags', - type = opt(table({ { 'nonblock', 'boolean', 'false' } })), - }, - { - name = 'write_flags', - type = opt(table({ { 'nonblock', 'boolean', 'false' } })), - }, + This function is not implemented on Unix, where it returns `ENOTSUP`. + ]], + returns = ret_or_fail('string', 'state'), + }, + }, + }, + { + title = '`uv_udp_t` - UDP handle', + id = 'uv_udp_t--udp-handle', + class = 'uv_udp_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + UDP handles encapsulate UDP communication for both clients and servers. + ]], + funcs = { + { + name = 'new_udp', + desc = [[ + Creates and initializes a new `uv_udp_t`. Returns the Lua userdata wrapping + it. The actual socket is created lazily. + + See [Constants][] for supported address `family` input values. + + When specified, `mmsgs` determines the number of messages able to be received + at one time via `recvmmsg(2)` (the allocated buffer will be sized to be able + to fit the specified number of max size dgrams). Only has an effect on + platforms that support `recvmmsg(2)`. + + **Note:** For backwards compatibility reasons, `flags` can also be a string or + integer. When it is a string, it will be treated like the `family` key above. + When it is an integer, it will be used directly as the `flags` parameter when + calling `uv_udp_init_ex`. + ]], + params = { + { + name = 'flags', + type = opt(table({ + { 'family', opt_str }, + { 'mmsgs', opt_int, '1' }, + })), }, - returns = ret_or_fail( - table({ - { 'read', 'integer', nil, '(file descriptor)' }, - { 'write', 'integer', nil, '(file descriptor)' }, - }), - 'fds' - ), - example = [[ - ```lua - -- Simple read/write with pipe_open - local fds = uv.pipe({nonblock=true}, {nonblock=true}) - - local read_pipe = uv.new_pipe() - read_pipe:open(fds.read) - - local write_pipe = uv.new_pipe() - write_pipe:open(fds.write) - - write_pipe:write("hello") - read_pipe:read_start(function(err, chunk) - assert(not err, err) - print(chunk) - end) - ``` - ]], }, - { - name = 'pipe_bind2', - method_form = 'pipe:bind2(name, [flags])', - desc = [[ - Bind the pipe to a file path (Unix) or a name (Windows). + returns = ret_or_fail('uv_udp_t', 'udp'), + }, + { + name = 'udp_get_send_queue_size', + method_form = 'udp:get_send_queue_size()', + desc = "Returns the handle's send queue size.", + params = { + { name = 'udp', type = 'uv_udp_t' }, + }, + returns = 'integer', + }, + { + name = 'udp_get_send_queue_count', + method_form = 'udp:get_send_queue_count()', + desc = "Returns the handle's send queue count.", + params = { + { name = 'udp', type = 'uv_udp_t' }, + }, + returns = 'integer', + }, + { + name = 'udp_open', + method_form = 'udp:open(fd)', + desc = [[ + Opens an existing file descriptor or Windows SOCKET as a UDP handle. - `Flags`: + Unix only: The only requirement of the sock argument is that it follows the + datagram contract (works in unconnected mode, supports sendmsg()/recvmsg(), + etc). In other words, other datagram-type sockets like raw sockets or netlink + sockets can also be passed to this function. - - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. - - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. - - If `type(flags)` is `nil`, it use default value `0`. - - Returns `EINVAL` for unsupported flags without performing the bind operation. + The file descriptor is set to non-blocking mode. - Supports Linux abstract namespace sockets. namelen must include the leading '\0' byte but not the trailing nul byte. - ]], - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - { name = 'name', type = 'string' }, - { name = 'flags', type = opt(union('integer', 'table')), default = '0' }, - }, - returns = success_ret, - notes = { - [[ - 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, - typically between 92 and 108 bytes. - 2. New in version 1.46.0. - ]], - }, + Note: The passed file descriptor or SOCKET is not checked for its type, but + it's required that it represents a valid datagram socket. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'fd', type = 'integer' }, }, - { - name = 'pipe_connect2', - method_form = 'pipe:connect2(name, [flags], [callback])', - desc = [[ - Connect to the Unix domain socket or the named pipe. - - `Flags`: - - - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. - - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. - - If `type(flags)` is `nil`, it use default value `0`. - - Returns `EINVAL` for unsupported flags without performing the bind operation. - - Supports Linux abstract namespace sockets. namelen must include the leading nul byte but not the trailing nul byte. - ]], - params = { - { name = 'pipe', type = 'uv_pipe_t' }, - { name = 'name', type = 'string' }, - { name = 'flags', type = opt(union('integer', 'table')), default = '0' }, - cb_err({}, true), - }, - returns = ret_or_fail('uv_connect_t', 'connect'), - notes = { - [[ - 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, - typically between 92 and 108 bytes. - 2. New in version 1.46.0. - ]], - }, + returns = success_ret, + }, + { + name = 'udp_bind', + method_form = 'udp:bind(host, port, [flags])', + desc = [[ + Bind the UDP handle to an IP address and port. Any `flags` are set with a table + with fields `reuseaddr` or `ipv6only` equal to `true` or `false`. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'host', type = 'string' }, + { name = 'port', type = 'number' }, + { + name = 'flags', + type = opt(table({ + { 'ipv6only', opt_bool }, + { 'reuseaddr', opt_bool }, + })), + }, + }, + returns = success_ret, + }, + { + name = 'udp_getsockname', + method_form = 'udp:getsockname()', + desc = 'Get the local IP and port of the UDP handle.', + params = { + { name = 'udp', type = 'uv_udp_t' }, + }, + returns = ret_or_fail('socketinfo', 'address'), + }, + { + name = 'udp_getpeername', + method_form = 'udp:getpeername()', + desc = [[ + Get the remote IP and port of the UDP handle on connected UDP handles. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, }, + returns = ret_or_fail('socketinfo', 'address'), }, - }, - { - title = '`uv_tty_t` - TTY handle', - id = 'uv_tty_t--tty-handle', - desc = [[ - > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. - - TTY handles represent a stream for the console. - - ```lua - -- Simple echo program - local stdin = uv.new_tty(0, true) - local stdout = uv.new_tty(1, false) - - stdin:read_start(function (err, data) - assert(not err, err) - if data then - stdout:write(data) - else - stdin:close() - stdout:close() - end - end) - ``` - ]], - methods = { - { - name = 'new_tty', - desc = [[ - Initialize a new TTY stream with the given file descriptor. Usually the file - descriptor will be: - - - 0 - stdin - - 1 - stdout - - 2 - stderr - - On Unix this function will determine the path of the fd of the terminal using - ttyname_r(3), open it, and use it if the passed file descriptor refers to a TTY. - This lets libuv put the tty in non-blocking mode without affecting other - processes that share the tty. - - This function is not thread safe on systems that don’t support ioctl TIOCGPTN or TIOCPTYGNAME, for instance OpenBSD and Solaris. - ]], - params = { - { name = 'fd', type = 'integer' }, - { name = 'readable', type = 'boolean' }, - }, - returns = ret_or_fail('uv_tty_t', 'tty'), - notes = { - 'If reopening the TTY fails, libuv falls back to blocking writes.', - }, + { + name = 'udp_set_membership', + method_form = 'udp:set_membership(multicast_addr, interface_addr, membership)', + desc = [[ + Set membership for a multicast address. `multicast_addr` is multicast address to + set membership for. `interface_addr` is interface address. `membership` can be + the string `"leave"` or `"join"`. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'multicast_addr', type = 'string' }, + { name = 'interface_addr', type = opt_str }, + { name = 'membership', type = 'string' }, }, - { - name = 'tty_set_mode', - method_form = 'tty:set_mode(mode)', - desc = [[ - Set the TTY using the specified terminal mode. - - See [Constants][] for supported TTY mode input values. - ]], - params = { - { name = 'tty', type = 'uv_tty_t' }, - { name = 'mode', type = 'string|integer' }, - }, - returns = success_ret, + returns = success_ret, + }, + { + name = 'udp_set_source_membership', + method_form = 'udp:set_source_membership(multicast_addr, interface_addr, source_addr, membership)', + desc = [[ + Set membership for a source-specific multicast group. `multicast_addr` is multicast + address to set membership for. `interface_addr` is interface address. `source_addr` + is source address. `membership` can be the string `"leave"` or `"join"`. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'multicast_addr', type = 'string' }, + { name = 'interface_addr', type = opt_str }, + { name = 'source_addr', type = 'string' }, + { name = 'membership', type = 'string' }, + }, + returns = success_ret, + }, + { + name = 'udp_set_multicast_loop', + method_form = 'udp:set_multicast_loop(on)', + desc = [[ + Set IP multicast loop flag. Makes multicast packets loop back to local + sockets. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'on', type = 'boolean' }, }, - { - name = 'tty_reset_mode', - desc = [[ - To be called when the program exits. Resets TTY settings to default values for - the next process to take over. + returns = success_ret, + }, + { + name = 'udp_set_multicast_ttl', + method_form = 'udp:set_multicast_ttl(ttl)', + desc = [[ + Set the multicast ttl. - This function is async signal-safe on Unix platforms but can fail with error - code `EBUSY` if you call it when execution is inside `uv.tty_set_mode()`. - ]], - returns = success_ret, - }, - { - name = 'tty_get_winsize', - method_form = 'tty:get_winsize()', - desc = 'Gets the current Window width and height.', - params = { - { name = 'tty', type = 'uv_tty_t' }, - }, - returns = ret_or_fail('integer, integer', 'width, height'), - }, - { - name = 'tty_set_vterm_state', - desc = [[ - Controls whether console virtual terminal sequences are processed by libuv or - console. Useful in particular for enabling ConEmu support of ANSI X3.64 and - Xterm 256 colors. Otherwise Windows10 consoles are usually detected - automatically. State should be one of: `"supported"` or `"unsupported"`. - - This function is only meaningful on Windows systems. On Unix it is silently - ignored. - ]], - params = { - { name = 'state', type = 'string' }, - }, + `ttl` is an integer 1 through 255. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'ttl', type = 'integer' }, }, - { - name = 'tty_get_vterm_state', - desc = [[ - Get the current state of whether console virtual terminal sequences are handled - by libuv or the console. The return value is `"supported"` or `"unsupported"`. + returns = success_ret, + }, + { + name = 'udp_set_multicast_interface', + method_form = 'udp:set_multicast_interface(interface_addr)', + desc = 'Set the multicast interface to send or receive data on.', + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'interface_addr', type = 'string' }, + }, + returns = success_ret, + }, + { + name = 'udp_set_broadcast', + method_form = 'udp:set_broadcast(on)', + desc = 'Set broadcast on or off.', + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'on', type = 'boolean' }, + }, + returns = success_ret, + }, + { + name = 'udp_set_ttl', + method_form = 'udp:set_ttl(ttl)', + desc = [[ + Set the time to live. - This function is not implemented on Unix, where it returns `ENOTSUP`. - ]], - returns = ret_or_fail('string', 'state'), + `ttl` is an integer 1 through 255. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'ttl', type = 'integer' }, }, + returns = success_ret, }, - }, - { - title = '`uv_udp_t` - UDP handle', - id = 'uv_udp_t--udp-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - UDP handles encapsulate UDP communication for both clients and servers. - ]], - methods = { - { - name = 'new_udp', - desc = [[ - Creates and initializes a new `uv_udp_t`. Returns the Lua userdata wrapping - it. The actual socket is created lazily. - - See [Constants][] for supported address `family` input values. - - When specified, `mmsgs` determines the number of messages able to be received - at one time via `recvmmsg(2)` (the allocated buffer will be sized to be able - to fit the specified number of max size dgrams). Only has an effect on - platforms that support `recvmmsg(2)`. - - **Note:** For backwards compatibility reasons, `flags` can also be a string or - integer. When it is a string, it will be treated like the `family` key above. - When it is an integer, it will be used directly as the `flags` parameter when - calling `uv_udp_init_ex`. - ]], - params = { - { - name = 'flags', - type = opt(table({ - { 'family', opt('string') }, - { 'mmsgs', opt('integer'), '1' }, - })), - }, - }, - returns = ret_or_fail('uv_udp_t', 'udp'), - }, - { - name = 'udp_get_send_queue_size', - method_form = 'udp:get_send_queue_size()', - desc = "Returns the handle's send queue size.", - returns = 'integer', - }, - { - name = 'udp_get_send_queue_count', - method_form = 'udp:get_send_queue_count()', - desc = "Returns the handle's send queue count.", - returns = 'integer', - }, - { - name = 'udp_open', - method_form = 'udp:open(fd)', - desc = [[ - Opens an existing file descriptor or Windows SOCKET as a UDP handle. - - Unix only: The only requirement of the sock argument is that it follows the - datagram contract (works in unconnected mode, supports sendmsg()/recvmsg(), - etc). In other words, other datagram-type sockets like raw sockets or netlink - sockets can also be passed to this function. - - The file descriptor is set to non-blocking mode. - - Note: The passed file descriptor or SOCKET is not checked for its type, but - it's required that it represents a valid datagram socket. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'fd', type = 'integer' }, + { + name = 'udp_send', + method_form = 'udp:send(data, host, port, callback)', + desc = [[ + Send data over the UDP socket. If the socket has not previously been bound + with `uv.udp_bind()` it will be bound to `0.0.0.0` (the "all interfaces" IPv4 + address) and a random port number. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'data', type = 'buffer' }, + { name = 'host', type = 'string' }, + { name = 'port', type = 'integer' }, + cb_err(), + }, + returns = ret_or_fail('uv_udp_send_t', 'send'), + }, + { + name = 'udp_try_send', + method_form = 'udp:try_send(data, host, port)', + desc = [[ + Same as `uv.udp_send()`, but won't queue a send request if it can't be + completed immediately. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'data', type = 'buffer' }, + { name = 'host', type = 'string' }, + { name = 'port', type = 'integer' }, + }, + returns = ret_or_fail('integer', 'bytes_sent'), + }, + { + name = 'udp_try_send2', + method_form = 'udp:try_send2(messages, flags)', + desc = [[ + Like `uv.udp_try_send()`, but can send multiple datagrams. + Lightweight abstraction around `sendmmsg(2)`, with a `sendmsg(2)` fallback loop + for platforms that do not support the former. The `udp` handle must be fully + initialized, either from a `uv.udp_bind` call, another call that will bind + automatically (`udp_send`, `udp_try_send`, etc), or from `uv.udp_connect`. + + `messages` should be an array-like table, where `addr` must be specified + if the `udp` has not been connected via `udp_connect`. Otherwise, `addr` + must be `nil`. + + `flags` is reserved for future extension and must currently be `nil` or `0` or + `{}`. + + Returns the number of messages sent successfully. An error will only be returned + if the first datagram failed to be sent. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { + name = 'messages', + type = dict( + 'integer', + table({ + { 'data', 'buffer' }, + { 'addr', table({ { 'ip', 'string' }, { 'port', 'integer' } }) }, + }) + ), }, - returns = success_ret, - }, - { - name = 'udp_bind', - method_form = 'udp:bind(host, port, [flags])', - desc = [[ - Bind the UDP handle to an IP address and port. Any `flags` are set with a table - with fields `reuseaddr` or `ipv6only` equal to `true` or `false`. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'host', type = 'string' }, - { name = 'port', type = 'number' }, + { name = 'flags', type = opt(union('0', table())) }, + { name = 'port', type = 'integer' }, + }, + returns = ret_or_fail('integer', 'messages_sent'), + example = [[ + ```lua + -- If client:connect(...) was not called + local addr = { ip = "127.0.0.1", port = 1234 } + client:try_send2({ + { data = "Message 1", addr = addr }, + { data = "Message 2", addr = addr }, + }) + + -- If client:connect(...) was called + client:try_send2({ + { data = "Message 1" }, + { data = "Message 2" }, + }) + ``` + ]], + }, + { + name = 'udp_recv_start', + method_form = 'udp:recv_start(callback)', + desc = [[ + Prepare for receiving data. If the socket has not previously been bound with + `uv.udp_bind()` it is bound to `0.0.0.0` (the "all interfaces" IPv4 address) + and a random port number. + + See [Constants][] for supported address `family` output values. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + cb_err({ + { 'data', opt_str }, { - name = 'flags', - type = opt(table({ - { 'ipv6only', opt('boolean') }, - { 'reuseaddr', opt('boolean') }, + 'addr', + opt(table({ + { 'ip', 'string' }, + { 'port', 'integer' }, + { 'family', 'string' }, })), }, - }, - returns = success_ret, - }, - { - name = 'udp_getsockname', - method_form = 'udp:getsockname()', - desc = 'Get the local IP and port of the UDP handle.', - params = { - { name = 'udp', type = 'uv_udp_t' }, - }, - returns = ret_or_fail('socketinfo', 'address'), - }, - { - name = 'udp_getpeername', - method_form = 'udp:getpeername()', - desc = [[ - Get the remote IP and port of the UDP handle on connected UDP handles. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - }, - returns = ret_or_fail('socketinfo', 'address'), - }, - { - name = 'udp_set_membership', - method_form = 'udp:set_membership(multicast_addr, interface_addr, membership)', - desc = [[ - Set membership for a multicast address. `multicast_addr` is multicast address to - set membership for. `interface_addr` is interface address. `membership` can be - the string `"leave"` or `"join"`. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'multicast_addr', type = 'string' }, - { name = 'interface_addr', type = opt('string') }, - { name = 'membership', type = 'string' }, - }, - returns = success_ret, - }, - { - name = 'udp_set_source_membership', - method_form = 'udp:set_source_membership(multicast_addr, interface_addr, source_addr, membership)', - desc = [[ - Set membership for a source-specific multicast group. `multicast_addr` is multicast - address to set membership for. `interface_addr` is interface address. `source_addr` - is source address. `membership` can be the string `"leave"` or `"join"`. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'multicast_addr', type = 'string' }, - { name = 'interface_addr', type = opt('string') }, - { name = 'source_addr', type = 'string' }, - { name = 'membership', type = 'string' }, - }, - returns = success_ret, - }, - { - name = 'udp_set_multicast_loop', - method_form = 'udp:set_multicast_loop(on)', - desc = [[ - Set IP multicast loop flag. Makes multicast packets loop back to local - sockets. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'on', type = 'boolean' }, - }, - returns = success_ret, - }, - { - name = 'udp_set_multicast_ttl', - method_form = 'udp:set_multicast_ttl(ttl)', - desc = [[ - Set the multicast ttl. - - `ttl` is an integer 1 through 255. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'ttl', type = 'integer' }, - }, - returns = success_ret, - }, - { - name = 'udp_set_multicast_interface', - method_form = 'udp:set_multicast_interface(interface_addr)', - desc = 'Set the multicast interface to send or receive data on.', - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'interface_addr', type = 'string' }, - }, - returns = success_ret, - }, - { - name = 'udp_set_broadcast', - method_form = 'udp:set_broadcast(on)', - desc = 'Set broadcast on or off.', - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'on', type = 'boolean' }, - }, - returns = success_ret, - }, - { - name = 'udp_set_ttl', - method_form = 'udp:set_ttl(ttl)', - desc = [[ - Set the time to live. - - `ttl` is an integer 1 through 255. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'ttl', type = 'integer' }, - }, - returns = success_ret, - }, - { - name = 'udp_send', - method_form = 'udp:send(data, host, port, callback)', - desc = [[ - Send data over the UDP socket. If the socket has not previously been bound - with `uv.udp_bind()` it will be bound to `0.0.0.0` (the "all interfaces" IPv4 - address) and a random port number. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'data', type = 'buffer' }, - { name = 'host', type = 'string' }, - { name = 'port', type = 'integer' }, - cb_err(), - }, - returns = ret_or_fail('uv_udp_send_t', 'send'), - }, - { - name = 'udp_try_send', - method_form = 'udp:try_send(data, host, port)', - desc = [[ - Same as `uv.udp_send()`, but won't queue a send request if it can't be - completed immediately. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'data', type = 'buffer' }, - { name = 'host', type = 'string' }, - { name = 'port', type = 'integer' }, - }, - returns = ret_or_fail('integer', 'bytes_sent'), - }, - { - name = 'udp_try_send2', - method_form = 'udp:try_send2(messages, flags)', - desc = [[ - Like `uv.udp_try_send()`, but can send multiple datagrams. - Lightweight abstraction around `sendmmsg(2)`, with a `sendmsg(2)` fallback loop - for platforms that do not support the former. The `udp` handle must be fully - initialized, either from a `uv.udp_bind` call, another call that will bind - automatically (`udp_send`, `udp_try_send`, etc), or from `uv.udp_connect`. - - `messages` should be an array-like table, where `addr` must be specified - if the `udp` has not been connected via `udp_connect`. Otherwise, `addr` - must be `nil`. - - `flags` is reserved for future extension and must currently be `nil` or `0` or - `{}`. - - Returns the number of messages sent successfully. An error will only be returned - if the first datagram failed to be sent. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, { - name = 'messages', - type = dict( - 'integer', - table({ - { 'data', 'buffer' }, - { 'addr', table({ { 'ip', 'string' }, { 'port', 'integer' } }) }, - }) - ), + 'flags', + table({ + { 'partial', opt_bool }, + { 'mmsg_chunk', opt_bool }, + }), }, - { name = 'flags', type = opt(union('0', table())) }, - { name = 'port', type = 'integer' }, - }, - returns = ret_or_fail('integer', 'messages_sent'), - example = [[ - ```lua - -- If client:connect(...) was not called - local addr = { ip = "127.0.0.1", port = 1234 } - client:try_send2({ - { data = "Message 1", addr = addr }, - { data = "Message 2", addr = addr }, - }) - - -- If client:connect(...) was called - client:try_send2({ - { data = "Message 1" }, - { data = "Message 2" }, - }) - ``` - ]], + }), }, - { - name = 'udp_recv_start', - method_form = 'udp:recv_start(callback)', - desc = [[ - Prepare for receiving data. If the socket has not previously been bound with - `uv.udp_bind()` it is bound to `0.0.0.0` (the "all interfaces" IPv4 address) - and a random port number. - - See [Constants][] for supported address `family` output values. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - cb_err({ - { 'data', opt('string') }, - { - 'addr', - opt(table({ - { 'ip', 'string' }, - { 'port', 'integer' }, - { 'family', 'string' }, - })), - }, - { - 'flags', - table({ - { 'partial', opt('boolean') }, - { 'mmsg_chunk', opt('boolean') }, - }), - }, - }), - }, - returns = success_ret, - }, - { - name = 'udp_recv_stop', - method_form = 'udp:recv_stop()', - desc = 'Stop listening for incoming datagrams.', - params = { - { name = 'udp', type = 'uv_udp_t' }, - }, - returns = success_ret, - }, - { - name = 'udp_connect', - method_form = 'udp:connect(host, port)', - desc = [[ - Associate the UDP handle to a remote address and port, so every message sent by - this handle is automatically sent to that destination. Calling this function - with a NULL addr disconnects the handle. Trying to call `uv.udp_connect()` on an - already connected handle will result in an `EISCONN` error. Trying to disconnect - a handle that is not connected will return an `ENOTCONN` error. - ]], - params = { - { name = 'udp', type = 'uv_udp_t' }, - { name = 'host', type = 'string' }, - { name = 'port', type = 'integer' }, - }, - returns = success_ret, + returns = success_ret, + }, + { + name = 'udp_recv_stop', + method_form = 'udp:recv_stop()', + desc = 'Stop listening for incoming datagrams.', + params = { + { name = 'udp', type = 'uv_udp_t' }, + }, + returns = success_ret, + }, + { + name = 'udp_connect', + method_form = 'udp:connect(host, port)', + desc = [[ + Associate the UDP handle to a remote address and port, so every message sent by + this handle is automatically sent to that destination. Calling this function + with a NULL addr disconnects the handle. Trying to call `uv.udp_connect()` on an + already connected handle will result in an `EISCONN` error. Trying to disconnect + a handle that is not connected will return an `ENOTCONN` error. + ]], + params = { + { name = 'udp', type = 'uv_udp_t' }, + { name = 'host', type = 'string' }, + { name = 'port', type = 'integer' }, }, + returns = success_ret, }, }, - { - title = '`uv_fs_event_t` - FS Event handle', - id = 'uv_fs_event_t--fs-event-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - FS Event handles allow the user to monitor a given path for changes, for - example, if the file was renamed or there was a generic change in it. This - handle uses the best backend for the job on each platform. - ]], - methods = { - { - name = 'new_fs_event', - desc = [[ - Creates and initializes a new `uv_fs_event_t`. Returns the Lua userdata wrapping - it. - ]], - returns = ret_or_fail('uv_fs_event_t', 'fs_event'), - }, - { - name = 'fs_event_start', - method_form = 'fs_event:start(path, flags, callback)', - desc = [[ - Start the handle with the given callback, which will watch the specified path - for changes. - ]], - params = { - { name = 'fs_event', type = 'uv_fs_event_t' }, - { name = 'path', type = 'string' }, - { - name = 'flags', - type = table({ - { 'watch_entry', opt('boolean'), 'false' }, - { 'stat', opt('boolean'), 'false' }, - { 'recursive', opt('boolean'), 'false' }, - }), - }, - cb_err({ - { 'filename', 'string' }, - { 'events', table({ { 'change', opt('boolean') }, { 'rename', opt('boolean') } }) }, + }, + { + title = '`uv_fs_event_t` - FS Event handle', + id = 'uv_fs_event_t--fs-event-handle', + class = 'uv_fs_event_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + FS Event handles allow the user to monitor a given path for changes, for + example, if the file was renamed or there was a generic change in it. This + handle uses the best backend for the job on each platform. + ]], + funcs = { + { + name = 'new_fs_event', + desc = [[ + Creates and initializes a new `uv_fs_event_t`. Returns the Lua userdata wrapping + it. + ]], + returns = ret_or_fail('uv_fs_event_t', 'fs_event'), + }, + { + name = 'fs_event_start', + method_form = 'fs_event:start(path, flags, callback)', + desc = [[ + Start the handle with the given callback, which will watch the specified path + for changes. + ]], + params = { + { name = 'fs_event', type = 'uv_fs_event_t' }, + { name = 'path', type = 'string' }, + { + name = 'flags', + type = table({ + { 'watch_entry', opt_bool, 'false' }, + { 'stat', opt_bool, 'false' }, + { 'recursive', opt_bool, 'false' }, }), }, - returns = success_ret, - }, - { - name = 'fs_event_stop', - method_form = 'fs_event:stop()', - desc = 'Stop the handle, the callback will no longer be called.', - returns = success_ret, - }, - { - name = 'fs_event_getpath', - method_form = 'fs_event:getpath()', - desc = 'Get the path being monitored by the handle.', - returns = ret_or_fail('string', 'path'), + cb_err({ + { 'filename', 'string' }, + { 'events', table({ { 'change', opt_bool }, { 'rename', opt_bool } }) }, + }), }, + returns = success_ret, + }, + { + name = 'fs_event_stop', + method_form = 'fs_event:stop()', + desc = 'Stop the handle, the callback will no longer be called.', + params = { + { name = 'fs_event', type = 'uv_fs_event_t' }, + }, + returns = success_ret, + }, + { + name = 'fs_event_getpath', + method_form = 'fs_event:getpath()', + desc = 'Get the path being monitored by the handle.', + params = { + { name = 'fs_event', type = 'uv_fs_event_t' }, + }, + returns = ret_or_fail('string', 'path'), }, }, - { - title = '`uv_fs_poll_t` - FS Poll handle', - id = 'uv_fs_poll_t--fs-poll-handle', - desc = [[ - > [`uv_handle_t`][] functions also apply. - - FS Poll handles allow the user to monitor a given path for changes. Unlike - `uv_fs_event_t`, fs poll handles use `stat` to detect when a file has changed so - they can work on file systems where fs event handles can't. - ]], - methods = { - { - name = 'new_fs_poll', - desc = [[ - Creates and initializes a new `uv_fs_poll_t`. Returns the Lua userdata wrapping - it. - ]], - returns = ret_or_fail('uv_fs_poll_t', 'fs_poll'), - }, - { - name = 'fs_poll_start', - method_form = 'fs_poll:start(path, interval, callback)', - desc = [[ - Check the file at `path` for changes every `interval` milliseconds. - - **Note:** For maximum portability, use multi-second intervals. Sub-second - intervals will not detect all changes on many file systems. - ]], - params = { - { name = 'fs_poll', type = 'uv_fs_poll_t' }, - { name = 'path', type = 'string' }, - { name = 'interval', type = 'integer' }, - cb_err({ - { 'prev', opt('table'), '(see `uv.fs_stat`)' }, - { 'curr', opt('table'), '(see `uv.fs_stat`)' }, - }), - }, - returns = success_ret, - }, - { - name = 'fs_poll_stop', - method_form = 'fs_poll:stop()', - desc = 'Stop the handle, the callback will no longer be called.', - returns = success_ret, - }, - { - name = 'fs_poll_getpath', - method_form = 'fs_poll:getpath()', - desc = 'Get the path being monitored by the handle.', - returns = ret_or_fail('string', 'path'), - }, + }, + { + title = '`uv_fs_poll_t` - FS Poll handle', + id = 'uv_fs_poll_t--fs-poll-handle', + class = 'uv_fs_poll_t', + desc = [[ + > [`uv_handle_t`][] functions also apply. + + FS Poll handles allow the user to monitor a given path for changes. Unlike + `uv_fs_event_t`, fs poll handles use `stat` to detect when a file has changed so + they can work on file systems where fs event handles can't. + ]], + funcs = { + { + name = 'new_fs_poll', + desc = [[ + Creates and initializes a new `uv_fs_poll_t`. Returns the Lua userdata wrapping + it. + ]], + returns = ret_or_fail('uv_fs_poll_t', 'fs_poll'), + }, + { + name = 'fs_poll_start', + method_form = 'fs_poll:start(path, interval, callback)', + desc = [[ + Check the file at `path` for changes every `interval` milliseconds. + + **Note:** For maximum portability, use multi-second intervals. Sub-second + intervals will not detect all changes on many file systems. + ]], + params = { + { name = 'fs_poll', type = 'uv_fs_poll_t' }, + { name = 'path', type = 'string' }, + { name = 'interval', type = 'integer' }, + cb_err({ + { 'prev', opt('table'), '(see `uv.fs_stat`)' }, + { 'curr', opt('table'), '(see `uv.fs_stat`)' }, + }), + }, + returns = success_ret, + }, + { + name = 'fs_poll_stop', + method_form = 'fs_poll:stop()', + desc = 'Stop the handle, the callback will no longer be called.', + params = { + { name = 'fs_poll', type = 'uv_fs_poll_t' }, + }, + returns = success_ret, + }, + { + name = 'fs_poll_getpath', + method_form = 'fs_poll:getpath()', + desc = 'Get the path being monitored by the handle.', + params = { + { name = 'fs_poll', type = 'uv_fs_poll_t' }, + }, + returns = ret_or_fail('string', 'path'), }, }, - { - title = 'File system operations', - id = 'file-system-operations', - desc = [[ - Most file system functions can operate synchronously or asynchronously. When a synchronous version is called (by omitting a callback), the function will - immediately return the results of the FS call. When an asynchronous version is - called (by providing a callback), the function will immediately return a - `uv_fs_t userdata` and asynchronously execute its callback; if an error is encountered, the first and only argument passed to the callback will be the `err` error string; if the operation completes successfully, the first argument will be `nil` and the remaining arguments will be the results of the FS call. - - Synchronous and asynchronous versions of `readFile` (with naive error handling) - are implemented below as an example: - - ```lua - local function readFileSync(path) - local fd = assert(uv.fs_open(path, "r", 438)) - local stat = assert(uv.fs_fstat(fd)) - local data = assert(uv.fs_read(fd, stat.size, 0)) - assert(uv.fs_close(fd)) - return data - end - - local data = readFileSync("main.lua") - print("synchronous read", data) - ``` - - ```lua - local function readFile(path, callback) - uv.fs_open(path, "r", 438, function(err, fd) + }, + { + title = 'File system operations', + id = 'file-system-operations', + desc = [[ + Most file system functions can operate synchronously or asynchronously. When a synchronous version is called (by omitting a callback), the function will + immediately return the results of the FS call. When an asynchronous version is + called (by providing a callback), the function will immediately return a + `uv_fs_t userdata` and asynchronously execute its callback; if an error is encountered, the first and only argument passed to the callback will be the `err` error string; if the operation completes successfully, the first argument will be `nil` and the remaining arguments will be the results of the FS call. + + Synchronous and asynchronous versions of `readFile` (with naive error handling) + are implemented below as an example: + + ```lua + local function readFileSync(path) + local fd = assert(uv.fs_open(path, "r", 438)) + local stat = assert(uv.fs_fstat(fd)) + local data = assert(uv.fs_read(fd, stat.size, 0)) + assert(uv.fs_close(fd)) + return data + end + + local data = readFileSync("main.lua") + print("synchronous read", data) + ``` + + ```lua + local function readFile(path, callback) + uv.fs_open(path, "r", 438, function(err, fd) + assert(not err, err) + uv.fs_fstat(fd, function(err, stat) assert(not err, err) - uv.fs_fstat(fd, function(err, stat) + uv.fs_read(fd, stat.size, 0, function(err, data) assert(not err, err) - uv.fs_read(fd, stat.size, 0, function(err, data) + uv.fs_close(fd, function(err) assert(not err, err) - uv.fs_close(fd, function(err) - assert(not err, err) - return callback(data) - end) + return callback(data) end) end) end) - end - - readFile("main.lua", function(data) - print("asynchronous read", data) end) - ``` - ]], - methods = { - { - name = 'fs_close', - desc = 'Equivalent to `close(2)`.', - params = { - { name = 'fd', type = 'integer' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_open', - desc = [[ - Equivalent to `open(2)`. Access `flags` may be an integer or one of: `"r"`, - `"rs"`, `"sr"`, `"r+"`, `"rs+"`, `"sr+"`, `"w"`, `"wx"`, `"xw"`, `"w+"`, - `"wx+"`, `"xw+"`, `"a"`, `"ax"`, `"xa"`, `"a+"`, `"ax+"`, or "`xa+`". + end + + readFile("main.lua", function(data) + print("asynchronous read", data) + end) + ``` + ]], + funcs = { + { + name = 'fs_close', + desc = 'Equivalent to `close(2)`.', + params = { + { name = 'fd', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_open', + desc = [[ + Equivalent to `open(2)`. Access `flags` may be an integer or one of: `"r"`, + `"rs"`, `"sr"`, `"r+"`, `"rs+"`, `"sr+"`, `"w"`, `"wx"`, `"xw"`, `"w+"`, + `"wx+"`, `"xw+"`, `"a"`, `"ax"`, `"xa"`, `"a+"`, `"ax+"`, or "`xa+`". + ]], + params = { + { name = 'path', type = 'string' }, + { name = 'flags', type = 'string|integer' }, + { + name = 'mode', + type = 'integer', + desc = "(octal `chmod(1)` mode, e.g. `tonumber('644', 8)`)", + }, + async_cb({ { 'fd', opt_int } }), + }, + returns_sync = ret_or_fail('integer', 'fd'), + returns_async = 'uv_fs_t', + notes = { + [[ + On Windows, libuv uses `CreateFileW` and thus the file is always + opened in binary mode. Because of this, the `O_BINARY` and `O_TEXT` flags are + not supported. ]], - params = { - { name = 'path', type = 'string' }, - { name = 'flags', type = 'string|integer' }, - { - name = 'mode', - type = 'integer', - desc = "(octal `chmod(1)` mode, e.g. `tonumber('644', 8)`)", - }, - async_cb({ { 'fd', opt('integer') } }), - }, - returns_sync = ret_or_fail('integer', 'fd'), - returns_async = 'uv_fs_t', - notes = { - [[ - On Windows, libuv uses `CreateFileW` and thus the file is always - opened in binary mode. Because of this, the `O_BINARY` and `O_TEXT` flags are - not supported. - ]], - }, }, - { - name = 'fs_read', - desc = [[ - Equivalent to `preadv(2)`. Returns any data. An empty string indicates EOF. + }, + { + name = 'fs_read', + desc = [[ + Equivalent to `preadv(2)`. Returns any data. An empty string indicates EOF. - If `offset` is nil or omitted, it will default to `-1`, which indicates 'use and update the current file offset.' + If `offset` is nil or omitted, it will default to `-1`, which indicates 'use and update the current file offset.' - **Note:** When `offset` is >= 0, the current file offset will not be updated by the read. - ]], - params = { - { name = 'fd', type = 'integer' }, - { name = 'size', type = 'integer' }, - { name = 'offset', type = opt('integer') }, - async_cb({ { 'data', opt('string') } }), - }, - returns_sync = ret_or_fail('string', 'data'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_unlink', - desc = 'Equivalent to `unlink(2)`.', - params = { - { name = 'path', type = 'string' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', + **Note:** When `offset` is >= 0, the current file offset will not be updated by the read. + ]], + params = { + { name = 'fd', type = 'integer' }, + { name = 'size', type = 'integer' }, + { name = 'offset', type = opt_int }, + async_cb({ { 'data', opt_str } }), }, - { - name = 'fs_write', - desc = [[ - Equivalent to `pwritev(2)`. Returns the number of bytes written. + returns_sync = ret_or_fail('string', 'data'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_unlink', + desc = 'Equivalent to `unlink(2)`.', + params = { + { name = 'path', type = 'string' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_write', + desc = [[ + Equivalent to `pwritev(2)`. Returns the number of bytes written. - If `offset` is nil or omitted, it will default to `-1`, which indicates 'use and update the current file offset.' + If `offset` is nil or omitted, it will default to `-1`, which indicates 'use and update the current file offset.' - **Note:** When `offset` is >= 0, the current file offset will not be updated by the write. - ]], - params = { - { name = 'fd', type = 'integer' }, - { name = 'data', type = 'buffer' }, - { name = 'offset', type = opt('integer') }, - async_cb({ { 'bytes', opt('integer') } }), - }, - returns_sync = ret_or_fail('integer', 'bytes_written'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_mkdir', - desc = 'Equivalent to `mkdir(2)`.', - params = { - { name = 'path', type = 'string' }, - { - name = 'mode', - type = 'integer', - desc = "(octal `chmod(1)` mode, e.g. `tonumber('755', 8)`)", - }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_mkdtemp', - desc = 'Equivalent to `mkdtemp(3)`.', - params = { - { name = 'template', type = 'string' }, - async_cb({ { 'path', opt('string') } }), - }, - returns_sync = ret_or_fail('string', 'path'), - returns_async = 'uv_fs_t', + **Note:** When `offset` is >= 0, the current file offset will not be updated by the write. + ]], + params = { + { name = 'fd', type = 'integer' }, + { name = 'data', type = 'buffer' }, + { name = 'offset', type = opt_int }, + async_cb({ { 'bytes', opt_int } }), }, - { - name = 'fs_mkstemp', - desc = [[ - Equivalent to `mkstemp(3)`. Returns a temporary file handle and filename. - ]], - params = { - { name = 'template', type = 'string' }, - async_cb({ { 'fd', opt('integer') }, { 'path', opt('string') } }), - }, - returns_sync = ret_or_fail('integer, string', 'fd, path'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_rmdir', - desc = 'Equivalent to `rmdir(2)`.', - params = { - { name = 'path', type = 'string' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_scandir', - desc = [[ - Equivalent to `scandir(3)`, with a slightly different API. Returns a handle that - the user can pass to `uv.fs_scandir_next()`. - - **Note:** This function can be used synchronously or asynchronously. The request - userdata is always synchronously returned regardless of whether a callback is - provided and the same userdata is passed to the callback if it is provided. - ]], - params = { - { name = 'path', type = 'string' }, - cb_err({ { 'success', opt('uv_fs_t') } }, true), - }, - returns = ret_or_fail('uv_fs_t', 'handle'), + returns_sync = ret_or_fail('integer', 'bytes_written'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_mkdir', + desc = 'Equivalent to `mkdir(2)`.', + params = { + { name = 'path', type = 'string' }, + { + name = 'mode', + type = 'integer', + desc = "(octal `chmod(1)` mode, e.g. `tonumber('755', 8)`)", + }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_mkdtemp', + desc = 'Equivalent to `mkdtemp(3)`.', + params = { + { name = 'template', type = 'string' }, + async_cb({ { 'path', opt_str } }), + }, + returns_sync = ret_or_fail('string', 'path'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_mkstemp', + desc = [[ + Equivalent to `mkstemp(3)`. Returns a temporary file handle and filename. + ]], + params = { + { name = 'template', type = 'string' }, + async_cb({ { 'fd', opt_int }, { 'path', opt_str } }), + }, + -- returns_sync = ret_or_fail('integer, string', 'fd, path'), + returns_sync = { + { opt_int, 'fd' }, + { 'string', 'path or err' }, + { opt('uv.error_name'), 'err_name' }, + }, + returns_sync_doc = '`integer, string` or `fail`', + returns_async = 'uv_fs_t', + }, + { + name = 'fs_rmdir', + desc = 'Equivalent to `rmdir(2)`.', + params = { + { name = 'path', type = 'string' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_scandir', + desc = [[ + Equivalent to `scandir(3)`, with a slightly different API. Returns a handle that + the user can pass to `uv.fs_scandir_next()`. + + **Note:** This function can be used synchronously or asynchronously. The request + userdata is always synchronously returned regardless of whether a callback is + provided and the same userdata is passed to the callback if it is provided. + ]], + params = { + { name = 'path', type = 'string' }, + cb_err({ { 'success', opt('uv_fs_t') } }, true), }, - { - name = 'fs_scandir_next', - desc = [[ - Called on a `uv_fs_t` returned by `uv.fs_scandir()` to get the next directory - entry data as a `name, type` pair. When there are no more entries, `nil` is - returned. + returns = ret_or_fail('uv_fs_t', 'handle'), + }, + { + name = 'fs_scandir_next', + desc = [[ + Called on a `uv_fs_t` returned by `uv.fs_scandir()` to get the next directory + entry data as a `name, type` pair. When there are no more entries, `nil` is + returned. - **Note:** This function only has a synchronous version. See `uv.fs_opendir` and - its related functions for an asynchronous version. - ]], - params = { - { name = 'fs', type = 'uv_fs_t' }, - }, - returns = ret_or_fail('[string, string]', 'name, type'), - returns_doc = '`string, string` or `nil` or `fail`', - }, - -- fs_stat.result - { - name = 'fs_stat', - desc = 'Equivalent to `stat(2)`.', - params = { - { name = 'path', type = 'string' }, - async_cb({ { 'stat', opt('fs_stat.result') } }), - }, - returns_sync = ret_or_fail('fs_stat.result', 'stat'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_fstat', - desc = 'Equivalent to `fstat(2)`.', - params = { - { name = 'fd', type = 'integer' }, - async_cb({ { 'stat', opt('fs_stat.result') } }), - }, - returns_sync = ret_or_fail('fs_stat.result', 'stat'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_lstat', - desc = 'Equivalent to `lstat(2)`.', - params = { - { name = 'path', type = 'string' }, - async_cb({ { 'stat', opt('fs_stat.result') } }), - }, - returns_sync = ret_or_fail('fs_stat.result', 'stat'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_rename', - desc = 'Equivalent to `rename(2)`.', - params = { - { name = 'path', type = 'string' }, - { name = 'new_path', type = 'string' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_fsync', - desc = 'Equivalent to `fsync(2)`.', - params = { - { name = 'fd', type = 'integer' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_fdatasync', - desc = 'Equivalent to `fdatasync(2)`.', - params = { - { name = 'fd', type = 'integer' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_ftruncate', - desc = 'Equivalent to `ftruncate(2)`.', - params = { - { name = 'fd', type = 'integer' }, - { name = 'offset', type = 'integer' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', + **Note:** This function only has a synchronous version. See `uv.fs_opendir` and + its related functions for an asynchronous version. + ]], + params = { + { name = 'fs', type = 'uv_fs_t' }, }, - { - name = 'fs_sendfile', - desc = [[ - Limited equivalent to `sendfile(2)`. Returns the number of bytes written. - ]], - params = { - { name = 'out_fd', type = 'integer' }, - { name = 'in_fd', type = 'integer' }, - { name = 'in_offset', type = 'integer' }, - { name = 'size', type = 'integer' }, - async_cb({ { 'bytes', opt('integer') } }), - }, - returns_sync = ret_or_fail('integer', 'bytes'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_access', - desc = [[ - Equivalent to `access(2)` on Unix. Windows uses `GetFileAttributesW()`. Access - `mode` can be an integer or a string containing `"R"` or `"W"` or `"X"`. - Returns `true` or `false` indicating access permission. - ]], - params = { - { name = 'path', type = 'string' }, - { - name = 'mode', - type = 'string', - desc = "(a combination of the `'r'`, `'w'` and `'x'` characters denoting the symbolic mode as per `chmod(1)`)", - }, - async_cb({ { 'permission', opt('boolean') } }), - }, - returns_sync = ret_or_fail('boolean', 'permission'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_chmod', - desc = 'Equivalent to `chmod(2)`.', - params = { - { name = 'path', type = 'string' }, - { - name = 'mode', - type = 'integer', - desc = "(octal `chmod(1)` mode, e.g. `tonumber('644', 8)`)", - }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_fchmod', - desc = 'Equivalent to `fchmod(2)`.', - params = { - { name = 'fd', type = 'integer' }, - { name = 'mode', type = 'integer' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_utime', - desc = 'Equivalent to `utime(2)`.', - params = { - { name = 'path', type = 'string' }, - { name = 'atime', type = 'number' }, - { name = 'mtime', type = 'number' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_futime', - desc = 'Equivalent to `futime(2)`.', - params = { - { name = 'fd', type = 'integer' }, - { name = 'atime', type = 'number' }, - { name = 'mtime', type = 'number' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_lutime', - desc = 'Equivalent to `lutime(2)`.', - params = { - { name = 'path', type = 'string' }, - { name = 'atime', type = 'number' }, - { name = 'mtime', type = 'number' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_link', - desc = 'Equivalent to `link(2)`.', - params = { - { name = 'path', type = 'string' }, - { name = 'new_path', type = 'string' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_symlink', - desc = 'Equivalent to `symlink(2)`. If the `flags` parameter is omitted, then the 3rd parameter will be treated as the `callback`.', - params = { - { name = 'path', type = 'string' }, - { name = 'new_path', type = 'string' }, - { - name = 'flags', - type = opt(union( - 'integer', - table({ - { - 'dir', - opt('boolean'), - }, - { 'junction', opt('boolean') }, - }) - )), - }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_readlink', - desc = 'Equivalent to `readlink(2)`.', - params = { - { name = 'path', type = 'string' }, - async_cb({ { 'path', opt('string') } }), - }, - returns_sync = ret_or_fail('string', 'path'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_realpath', - desc = 'Equivalent to `realpath(3)`.', - params = { - { name = 'path', type = 'string' }, - async_cb({ { 'path', opt('string') } }), - }, - returns_sync = ret_or_fail('string', 'path'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_chown', - desc = 'Equivalent to `chown(2)`.', - params = { - { name = 'path', type = 'string' }, - { name = 'uid', type = 'integer' }, - { name = 'gid', type = 'integer' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_fchown', - desc = 'Equivalent to `fchown(2)`.', - params = { - { name = 'fd', type = 'integer' }, - { name = 'uid', type = 'integer' }, - { name = 'gid', type = 'integer' }, - async_cb(), + returns = { + { opt_str, 'name' }, + { 'string', 'type or err' }, + { opt('uv.error_name'), 'err_name' }, + }, + returns_doc = '`string, string` or `nil` or `fail`', + }, + -- fs_stat.result + { + name = 'fs_stat', + desc = 'Equivalent to `stat(2)`.', + params = { + { name = 'path', type = 'string' }, + async_cb({ { 'stat', opt('fs_stat.result') } }), + }, + returns_sync = ret_or_fail('fs_stat.result', 'stat'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_fstat', + desc = 'Equivalent to `fstat(2)`.', + params = { + { name = 'fd', type = 'integer' }, + async_cb({ { 'stat', opt('fs_stat.result') } }), + }, + returns_sync = ret_or_fail('fs_stat.result', 'stat'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_lstat', + desc = 'Equivalent to `lstat(2)`.', + params = { + { name = 'path', type = 'string' }, + async_cb({ { 'stat', opt('fs_stat.result') } }), + }, + returns_sync = ret_or_fail('fs_stat.result', 'stat'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_rename', + desc = 'Equivalent to `rename(2)`.', + params = { + { name = 'path', type = 'string' }, + { name = 'new_path', type = 'string' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_fsync', + desc = 'Equivalent to `fsync(2)`.', + params = { + { name = 'fd', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_fdatasync', + desc = 'Equivalent to `fdatasync(2)`.', + params = { + { name = 'fd', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_ftruncate', + desc = 'Equivalent to `ftruncate(2)`.', + params = { + { name = 'fd', type = 'integer' }, + { name = 'offset', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_sendfile', + desc = [[ + Limited equivalent to `sendfile(2)`. Returns the number of bytes written. + ]], + params = { + { name = 'out_fd', type = 'integer' }, + { name = 'in_fd', type = 'integer' }, + { name = 'in_offset', type = 'integer' }, + { name = 'size', type = 'integer' }, + async_cb({ { 'bytes', opt_int } }), + }, + returns_sync = ret_or_fail('integer', 'bytes'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_access', + desc = [[ + Equivalent to `access(2)` on Unix. Windows uses `GetFileAttributesW()`. Access + `mode` can be an integer or a string containing `"R"` or `"W"` or `"X"`. + Returns `true` or `false` indicating access permission. + ]], + params = { + { name = 'path', type = 'string' }, + { + name = 'mode', + type = 'string', + desc = "(a combination of the `'r'`, `'w'` and `'x'` characters denoting the symbolic mode as per `chmod(1)`)", + }, + async_cb({ { 'permission', opt_bool } }), + }, + returns_sync = ret_or_fail('boolean', 'permission'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_chmod', + desc = 'Equivalent to `chmod(2)`.', + params = { + { name = 'path', type = 'string' }, + { + name = 'mode', + type = 'integer', + desc = "(octal `chmod(1)` mode, e.g. `tonumber('644', 8)`)", + }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_fchmod', + desc = 'Equivalent to `fchmod(2)`.', + params = { + { name = 'fd', type = 'integer' }, + { name = 'mode', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_utime', + desc = 'Equivalent to `utime(2)`.', + params = { + { name = 'path', type = 'string' }, + { name = 'atime', type = 'number' }, + { name = 'mtime', type = 'number' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_futime', + desc = 'Equivalent to `futime(2)`.', + params = { + { name = 'fd', type = 'integer' }, + { name = 'atime', type = 'number' }, + { name = 'mtime', type = 'number' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_lutime', + desc = 'Equivalent to `lutime(2)`.', + params = { + { name = 'path', type = 'string' }, + { name = 'atime', type = 'number' }, + { name = 'mtime', type = 'number' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_link', + desc = 'Equivalent to `link(2)`.', + params = { + { name = 'path', type = 'string' }, + { name = 'new_path', type = 'string' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_symlink', + desc = 'Equivalent to `symlink(2)`. If the `flags` parameter is omitted, then the 3rd parameter will be treated as the `callback`.', + params = { + { name = 'path', type = 'string' }, + { name = 'new_path', type = 'string' }, + { + name = 'flags', + type = opt(union( + 'integer', + table({ + { + 'dir', + opt_bool, + }, + { 'junction', opt_bool }, + }) + )), }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_lchown', - desc = 'Equivalent to `lchown(2)`.', - params = { - { name = 'fd', type = 'integer' }, - { name = 'uid', type = 'integer' }, - { name = 'gid', type = 'integer' }, - async_cb(), + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_readlink', + desc = 'Equivalent to `readlink(2)`.', + params = { + { name = 'path', type = 'string' }, + async_cb({ { 'path', opt_str } }), + }, + returns_sync = ret_or_fail('string', 'path'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_realpath', + desc = 'Equivalent to `realpath(3)`.', + params = { + { name = 'path', type = 'string' }, + async_cb({ { 'path', opt_str } }), + }, + returns_sync = ret_or_fail('string', 'path'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_chown', + desc = 'Equivalent to `chown(2)`.', + params = { + { name = 'path', type = 'string' }, + { name = 'uid', type = 'integer' }, + { name = 'gid', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_fchown', + desc = 'Equivalent to `fchown(2)`.', + params = { + { name = 'fd', type = 'integer' }, + { name = 'uid', type = 'integer' }, + { name = 'gid', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_lchown', + desc = 'Equivalent to `lchown(2)`.', + params = { + { name = 'fd', type = 'integer' }, + { name = 'uid', type = 'integer' }, + { name = 'gid', type = 'integer' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_copyfile', + desc = [[ + Copies a file from path to new_path. If the `flags` parameter is omitted, then the 3rd parameter will be treated as the `callback`. + ]], + params = { + { name = 'path', type = 'string' }, + { name = 'new_path', type = 'string' }, + { + name = 'flags', + type = opt(union( + 'integer', + table({ + { 'excl', opt_bool }, + { 'ficlone', opt_bool }, + { 'ficlone_force', opt_bool }, + }) + )), }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', + async_cb(), }, - { - name = 'fs_copyfile', - desc = [[ - Copies a file from path to new_path. If the `flags` parameter is omitted, then the 3rd parameter will be treated as the `callback`. - ]], - params = { - { name = 'path', type = 'string' }, - { name = 'new_path', type = 'string' }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_opendir', + desc = [[ + Opens path as a directory stream. Returns a handle that the user can pass to + `uv.fs_readdir()`. The `entries` parameter defines the maximum number of entries + that should be returned by each call to `uv.fs_readdir()`. + ]], + params = { + { name = 'path', type = 'string' }, + async_cb({ { 'dir', opt('luv_dir_t') } }), + { name = 'entries', type = opt_int }, + }, + returns_sync = ret_or_fail('luv_dir_t', 'dir'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_readdir', + method_form = 'dir:readdir([callback])', + desc = [[ + Iterates over the directory stream `luv_dir_t` returned by a successful + `uv.fs_opendir()` call. A table of data tables is returned where the number + of entries `n` is equal to or less than the `entries` parameter used in + the associated `uv.fs_opendir()` call. + ]], + params = { + { name = 'dir', type = 'luv_dir_t' }, + async_cb({ { - name = 'flags', - type = opt(union( - 'integer', - table({ - { 'excl', opt('boolean') }, - { 'ficlone', opt('boolean') }, - { 'ficlone_force', opt('boolean') }, - }) - )), + 'entries', + opt(dict('integer', table({ { 'name', 'string' }, { 'type', 'string' } }))), }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_opendir', - desc = [[ - Opens path as a directory stream. Returns a handle that the user can pass to - `uv.fs_readdir()`. The `entries` parameter defines the maximum number of entries - that should be returned by each call to `uv.fs_readdir()`. - ]], - params = { - { name = 'path', type = 'string' }, - async_cb({ { 'dir', opt('luv_dir_t') } }), - { name = 'entries', type = opt('integer') }, - }, - returns_sync = ret_or_fail('luv_dir_t', 'dir'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_readdir', - method_form = 'dir:readdir([callback])', - desc = [[ - Iterates over the directory stream `luv_dir_t` returned by a successful - `uv.fs_opendir()` call. A table of data tables is returned where the number - of entries `n` is equal to or less than the `entries` parameter used in - the associated `uv.fs_opendir()` call. - ]], - params = { - { name = 'dir', type = 'luv_dir_t' }, - async_cb({ - { - 'entries', - opt(dict('integer', table({ { 'name', 'string' }, { 'type', 'string' } }))), - }, - }), - }, - returns_sync = ret_or_fail( - dict('integer', table({ { 'name', 'string' }, { 'type', 'string ' } })), - 'entries' - ), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_closedir', - desc = 'Closes a directory stream returned by a successful `uv.fs_opendir()` call.', - method_form = 'dir:closedir([callback])', - params = { - { name = 'dir', type = 'luv_dir_t' }, - async_cb(), - }, - returns_sync = ret_or_fail('boolean', 'success'), - returns_async = 'uv_fs_t', - }, - { - name = 'fs_statfs', - desc = 'Equivalent to `statfs(2)`.', - params = { - { name = 'path', type = 'string' }, - async_cb({ { 'stat', opt('fs_statfs.result') } }), - }, - returns_sync = ret_or_fail('fs_statfs.result', 'stat'), - returns_async = 'uv_fs_t', + }), }, + returns_sync = ret_or_fail( + dict('integer', table({ { 'name', 'string' }, { 'type', 'string ' } })), + 'entries' + ), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_closedir', + desc = 'Closes a directory stream returned by a successful `uv.fs_opendir()` call.', + method_form = 'dir:closedir([callback])', + params = { + { name = 'dir', type = 'luv_dir_t' }, + async_cb(), + }, + returns_sync = ret_or_fail('boolean', 'success'), + returns_async = 'uv_fs_t', + }, + { + name = 'fs_statfs', + desc = 'Equivalent to `statfs(2)`.', + params = { + { name = 'path', type = 'string' }, + async_cb({ { 'stat', opt('fs_statfs.result') } }), + }, + returns_sync = ret_or_fail('fs_statfs.result', 'stat'), + returns_async = 'uv_fs_t', }, }, - { - title = 'Thread pool work scheduling', - id = 'thread-pool-work-scheduling', - desc = [[ - Libuv provides a threadpool which can be used to run user code and get notified - in the loop thread. This threadpool is internally used to run all file system - operations, as well as `getaddrinfo` and `getnameinfo` requests. - - ```lua - local function work_callback(a, b) - return a + b - end - - local function after_work_callback(c) - print("The result is: " .. c) - end - - local work = uv.new_work(work_callback, after_work_callback) - - work:queue(1, 2) - - -- output: "The result is: 3" - ``` - - ]], - methods = { - { - name = 'new_work', - desc = [[ - Creates and initializes a new `luv_work_ctx_t` (not `uv_work_t`). - `work_callback` is a Lua function or a string containing Lua code or bytecode dumped from a function. - Returns the Lua userdata wrapping it. - ]], - params = { - { - name = 'work_callback', - type = union( - 'string', - fun({ - { '...', 'threadargs', 'passed to/from `uv.queue_work(work_ctx, ...)`' }, - }) - ), - }, - { - name = 'after_work_callback', - type = fun({ - { '...', 'threadargs', 'returned from `work_callback`' }, - }), - }, + }, + { + title = 'Thread pool work scheduling', + id = 'thread-pool-work-scheduling', + desc = [[ + Libuv provides a threadpool which can be used to run user code and get notified + in the loop thread. This threadpool is internally used to run all file system + operations, as well as `getaddrinfo` and `getnameinfo` requests. + + ```lua + local function work_callback(a, b) + return a + b + end + + local function after_work_callback(c) + print("The result is: " .. c) + end + + local work = uv.new_work(work_callback, after_work_callback) + + work:queue(1, 2) + + -- output: "The result is: 3" + ``` + + ]], + funcs = { + { + name = 'new_work', + desc = [[ + Creates and initializes a new `luv_work_ctx_t` (not `uv_work_t`). + `work_callback` is a Lua function or a string containing Lua code or bytecode dumped from a function. + Returns the Lua userdata wrapping it. + ]], + params = { + { + name = 'work_callback', + type = union( + 'string', + fun({ + { '...', 'threadargs', 'passed to/from `uv.queue_work(work_ctx, ...)`' }, + }) + ), }, - returns = 'luv_work_ctx_t', - }, - { - name = 'queue_work', - method_form = 'work_ctx:queue(...)', - desc = [[ - Queues a work request which will run `work_callback` in a new Lua state in a - thread from the threadpool with any additional arguments from `...`. Values - returned from `work_callback` are passed to `after_work_callback`, which is - called in the main loop thread. - ]], - params = { - { name = 'work_ctx', type = 'luv_work_ctx_t' }, - { name = '...', type = 'threadargs' }, + { + name = 'after_work_callback', + type = fun({ + { '...', 'threadargs', 'returned from `work_callback`' }, + }), }, - returns = ret_or_fail('boolean', 'success'), }, + returns = 'luv_work_ctx_t', }, - }, - { - title = 'DNS utility functions', - id = 'dns-utility-functions', - methods = { - { - name = 'getaddrinfo', - desc = [[ - Equivalent to `getaddrinfo(3)`. Either `node` or `service` may be `nil` but not - both. - - See [Constants][] for supported address `family` input and output values. - - See [Constants][] for supported `socktype` input and output values. - - When `protocol` is set to 0 or nil, it will be automatically chosen based on the - socket's domain and type. When `protocol` is specified as a string, it will be - looked up using the `getprotobyname(3)` function. Examples: `"ip"`, `"icmp"`, - `"tcp"`, `"udp"`, etc. - ]], - params = { - { name = 'host', type = opt('string') }, - { name = 'service', type = opt('string') }, - { name = 'hints', type = opt('getaddrinfo.hints') }, - async_cb({ { 'addresses', opt('addresses') } }), - }, - returns_sync = ret_or_fail('addresses', 'addresses'), - returns_async = ret_or_fail('uv_getaddrinfo_t', 'addrinfo'), + { + name = 'queue_work', + method_form = 'work_ctx:queue(...)', + desc = [[ + Queues a work request which will run `work_callback` in a new Lua state in a + thread from the threadpool with any additional arguments from `...`. Values + returned from `work_callback` are passed to `after_work_callback`, which is + called in the main loop thread. + ]], + params = { + { name = 'work_ctx', type = 'luv_work_ctx_t' }, + { name = '...', type = 'threadargs' }, }, - { - name = 'getnameinfo', - desc = [[ - Equivalent to `getnameinfo(3)`. + returns = ret_or_fail('boolean', 'success'), + }, + }, + }, + { + title = 'DNS utility functions', + id = 'dns-utility-functions', + funcs = { + { + name = 'getaddrinfo', + desc = [[ + Equivalent to `getaddrinfo(3)`. Either `node` or `service` may be `nil` but not + both. + + See [Constants][] for supported address `family` input and output values. + + See [Constants][] for supported `socktype` input and output values. + + When `protocol` is set to 0 or nil, it will be automatically chosen based on the + socket's domain and type. When `protocol` is specified as a string, it will be + looked up using the `getprotobyname(3)` function. Examples: `"ip"`, `"icmp"`, + `"tcp"`, `"udp"`, etc. + ]], + params = { + { name = 'host', type = opt_str }, + { name = 'service', type = opt_str }, + { + name = 'hints', + type = opt(table({ + { 'family', opt(union('string', 'integer')) }, + { 'socktype', opt(union('string', 'integer')) }, + { 'protocol', opt(union('string', 'integer')) }, + { 'addrconfig', opt_bool }, + { 'v4mapped', opt_bool }, + { 'all', opt_bool }, + { 'numerichost', opt_bool }, + { 'passive', opt_bool }, + { 'numericserv', opt_bool }, + { 'canonname', opt_bool }, + })), + }, + async_cb({ { 'addresses', opt(dict('integer', 'address')) } }), + }, + returns_sync = ret_or_fail(dict('integer', 'address'), 'addresses'), + returns_async = ret_or_fail('uv_getaddrinfo_t', 'addrinfo'), + }, + { + name = 'getnameinfo', + desc = [[ + Equivalent to `getnameinfo(3)`. - See [Constants][] for supported address `family` input values. - ]], - params = { - { - name = 'address', - type = table({ - { 'ip', opt('string') }, - { 'port', opt('integer') }, - { 'family', opt(union('string', 'integer')) }, - }), - }, - async_cb({ { 'host', opt('string') }, { 'service', opt('string') } }), + See [Constants][] for supported address `family` input values. + ]], + params = { + { + name = 'address', + type = table({ + { 'ip', opt_str }, + { 'port', opt_int }, + { 'family', opt(union('string', 'integer')) }, + }), }, - returns_sync = ret_or_fail('string, string', 'host, service'), - returns_async = ret_or_fail('uv_getnameinfo_t', 'nameinfo'), + async_cb({ { 'host', opt_str }, { 'service', opt_str } }), + }, + returns_sync = { + { opt_str, 'host' }, + { 'string', 'service or err' }, + { opt('uv.error_name'), 'err_name' }, }, + returns_sync_doc = '`string, string` or `fail`', + returns_async = ret_or_fail('uv_getnameinfo_t', 'nameinfo'), }, }, - { - title = 'Threading and synchronization utilities', - id = 'threading-and-synchronization-utilities', - desc = [[ - Libuv provides cross-platform implementations for multiple threading and - synchronization primitives. The API largely follows the pthreads API. - ]], - methods = { - { - name = 'new_thread', - desc = [[ - Creates and initializes a `luv_thread_t` (not `uv_thread_t`). Returns the Lua - userdata wrapping it and asynchronously executes `entry`, which can be either - a Lua function or a string containing Lua code or bytecode dumped from a function. Additional arguments `...` - are passed to the `entry` function and an optional `options` table may be - provided. Currently accepted `option` fields are `stack_size`. - ]], - params = { - { - name = 'options', - type = opt(table({ - { 'stack_size', opt('integer') }, - })), - }, - { name = 'entry', type = 'function|string' }, - { name = '...', type = 'threadargs', desc = 'passed to `entry`' }, - }, - returns = ret_or_fail('luv_thread_t', 'thread'), - notes = { - 'unsafe, please make sure the thread end of life before Lua state close.', + }, + { + title = 'Threading and synchronization utilities', + id = 'threading-and-synchronization-utilities', + desc = [[ + Libuv provides cross-platform implementations for multiple threading and + synchronization primitives. The API largely follows the pthreads API. + ]], + funcs = { + { + name = 'new_thread', + desc = [[ + Creates and initializes a `luv_thread_t` (not `uv_thread_t`). Returns the Lua + userdata wrapping it and asynchronously executes `entry`, which can be either + a Lua function or a string containing Lua code or bytecode dumped from a function. Additional arguments `...` + are passed to the `entry` function and an optional `options` table may be + provided. Currently accepted `option` fields are `stack_size`. + ]], + params = { + { + name = 'options', + type = opt(table({ + { 'stack_size', opt_int }, + })), }, + { name = 'entry', type = 'function|string' }, + { name = '...', type = 'threadargs', desc = 'passed to `entry`' }, }, - { - name = 'thread_equal', - method_form = 'thread:equal(other_thread)', - desc = [[ - Returns a boolean indicating whether two threads are the same. This function is - equivalent to the `__eq` metamethod. - ]], - params = { - { name = 'thread', type = 'luv_thread_t' }, - { name = 'other_thread', type = 'luv_thread_t' }, - }, - returns = 'boolean', - }, - { - name = 'thread_setaffinity', - method_form = 'thread:setaffinity(affinity, [get_old_affinity])', - desc = [[ - Sets the specified thread's affinity setting. - - `affinity` must be a table where each of the keys are a CPU number and the - values are booleans that represent whether the `thread` should be eligible to - run on that CPU. If the length of the `affinity` table is not greater than or - equal to `uv.cpumask_size()`, any CPU numbers missing from the table will have - their affinity set to `false`. If setting the affinity of more than - `uv.cpumask_size()` CPUs is desired, `affinity` must be an array-like table - with no gaps, since `#affinity` will be used as the `cpumask_size` if it is - greater than `uv.cpumask_size()`. - - If `get_old_affinity` is `true`, the previous affinity settings for the `thread` - will be returned. Otherwise, `true` is returned after a successful call. - - **Note:** Thread affinity setting is not atomic on Windows. Unsupported on macOS. - ]], - params = { - { name = 'thread', type = 'luv_thread_t' }, - { name = 'affinity', type = dict('integer', 'boolean') }, - { name = 'get_old_affinity', type = opt('boolean') }, - }, - -- TODO: can also return boolean - returns = ret_or_fail(dict('integer', 'boolean'), 'affinity'), - }, - { - name = 'thread_getaffinity', - method_form = 'thread:getaffinity([mask_size])', - desc = [[ - Gets the specified thread's affinity setting. - - If `mask_size` is provided, it must be greater than or equal to - `uv.cpumask_size()`. If the `mask_size` parameter is omitted, then the return - of `uv.cpumask_size()` will be used. Returns an array-like table where each of - the keys correspond to a CPU number and the values are booleans that represent - whether the `thread` is eligible to run on that CPU. - - **Note:** Thread affinity getting is not atomic on Windows. Unsupported on macOS. - ]], - params = { - { name = 'thread', type = 'luv_thread_t' }, - { name = 'mask_size', type = opt('integer') }, - }, - returns = ret_or_fail(dict('integer', 'boolean'), 'affinity'), + returns = ret_or_fail('luv_thread_t', 'thread'), + notes = { + 'unsafe, please make sure the thread end of life before Lua state close.', }, - { - name = 'thread_getcpu', - desc = [[ - Gets the CPU number on which the calling thread is running. - - **Note:** The first CPU will be returned as the number 1, not 0. This allows for - the number to correspond with the table keys used in `uv.thread_getaffinity` and - `uv.thread_setaffinity`. - ]], - returns = ret_or_fail('integer', 'cpu'), - }, - { - name = 'thread_setpriority', - method_form = 'thread:setpriority(priority)', - desc = [[ - Sets the specified thread's scheduling priority setting. It requires elevated - privilege to set specific priorities on some platforms. - - The priority can be set to the following constants. - - - uv.constants.THREAD_PRIORITY_HIGHEST - - uv.constants.THREAD_PRIORITY_ABOVE_NORMAL - - uv.constants.THREAD_PRIORITY_NORMAL - - uv.constants.THREAD_PRIORITY_BELOW_NORMAL - - uv.constants.THREAD_PRIORITY_LOWEST - ]], - params = { - { name = 'thread', type = 'luv_thread_t' }, - { name = 'priority', type = 'integer' }, - }, - returns = ret_or_fail('boolean', 'success'), + }, + { + name = 'thread_equal', + method_form = 'thread:equal(other_thread)', + desc = [[ + Returns a boolean indicating whether two threads are the same. This function is + equivalent to the `__eq` metamethod. + ]], + params = { + { name = 'thread', type = 'luv_thread_t' }, + { name = 'other_thread', type = 'luv_thread_t' }, + }, + returns = 'boolean', + }, + { + name = 'thread_setaffinity', + method_form = 'thread:setaffinity(affinity, [get_old_affinity])', + desc = [[ + Sets the specified thread's affinity setting. + + `affinity` must be a table where each of the keys are a CPU number and the + values are booleans that represent whether the `thread` should be eligible to + run on that CPU. If the length of the `affinity` table is not greater than or + equal to `uv.cpumask_size()`, any CPU numbers missing from the table will have + their affinity set to `false`. If setting the affinity of more than + `uv.cpumask_size()` CPUs is desired, `affinity` must be an array-like table + with no gaps, since `#affinity` will be used as the `cpumask_size` if it is + greater than `uv.cpumask_size()`. + + If `get_old_affinity` is `true`, the previous affinity settings for the `thread` + will be returned. Otherwise, `true` is returned after a successful call. + + **Note:** Thread affinity setting is not atomic on Windows. Unsupported on macOS. + ]], + params = { + { name = 'thread', type = 'luv_thread_t' }, + { name = 'affinity', type = dict('integer', 'boolean') }, + { name = 'get_old_affinity', type = opt_bool }, + }, + -- TODO: can also return boolean + returns = ret_or_fail(dict('integer', 'boolean'), 'affinity'), + }, + { + name = 'thread_getaffinity', + method_form = 'thread:getaffinity([mask_size])', + desc = [[ + Gets the specified thread's affinity setting. + + If `mask_size` is provided, it must be greater than or equal to + `uv.cpumask_size()`. If the `mask_size` parameter is omitted, then the return + of `uv.cpumask_size()` will be used. Returns an array-like table where each of + the keys correspond to a CPU number and the values are booleans that represent + whether the `thread` is eligible to run on that CPU. + + **Note:** Thread affinity getting is not atomic on Windows. Unsupported on macOS. + ]], + params = { + { name = 'thread', type = 'luv_thread_t' }, + { name = 'mask_size', type = opt_int }, }, - { - name = 'thread_getpriority', - method_form = 'thread:getpriority()', - desc = [[ - Gets the thread's priority setting. + returns = ret_or_fail(dict('integer', 'boolean'), 'affinity'), + }, + { + name = 'thread_getcpu', + desc = [[ + Gets the CPU number on which the calling thread is running. + + **Note:** The first CPU will be returned as the number 1, not 0. This allows for + the number to correspond with the table keys used in `uv.thread_getaffinity` and + `uv.thread_setaffinity`. + ]], + returns = ret_or_fail('integer', 'cpu'), + }, + { + name = 'thread_setpriority', + method_form = 'thread:setpriority(priority)', + desc = [[ + Sets the specified thread's scheduling priority setting. It requires elevated + privilege to set specific priorities on some platforms. + + The priority can be set to the following constants. + + - uv.constants.THREAD_PRIORITY_HIGHEST + - uv.constants.THREAD_PRIORITY_ABOVE_NORMAL + - uv.constants.THREAD_PRIORITY_NORMAL + - uv.constants.THREAD_PRIORITY_BELOW_NORMAL + - uv.constants.THREAD_PRIORITY_LOWEST + ]], + params = { + { name = 'thread', type = 'luv_thread_t' }, + { name = 'priority', type = 'integer' }, + }, + returns = ret_or_fail('boolean', 'success'), + }, + { + name = 'thread_getpriority', + method_form = 'thread:getpriority()', + desc = [[ + Gets the thread's priority setting. - Retrieves the scheduling priority of the specified thread. The returned priority - value is platform dependent. + Retrieves the scheduling priority of the specified thread. The returned priority + value is platform dependent. - For Linux, when schedule policy is SCHED_OTHER (default), priority is 0. - ]], - params = { - { name = 'thread', type = 'luv_thread_t' }, - }, - returns = ret_or_fail('integer', 'priority'), - }, - { - name = 'thread_self', - desc = 'Returns the handle for the thread in which this is called.', - returns = 'luv_thread_t', - }, - { - name = 'thread_join', - method_form = 'thread:join()', - desc = 'Waits for the `thread` to finish executing its entry function.', - params = { - { name = 'thread', type = 'luv_thread_t' }, - }, - returns = ret_or_fail('boolean', 'success'), - }, - { - name = 'thread_detach', - method_form = 'thread:detach()', - desc = [[ - Detaches a thread. Detached threads automatically release their resources upon - termination, eliminating the need for the application to call `uv.thread_join`. - ]], - params = { - { name = 'thread', type = 'luv_thread_t' }, - }, - returns = ret_or_fail('boolean', 'success'), - }, - { - name = 'thread_setname', - desc = [[ - Sets the name of the current thread. Different platforms define different limits - on the max number of characters a thread name can be: Linux, IBM i (16), macOS - (64), Windows (32767), and NetBSD (32), etc. The name will be truncated - if `name` is larger than the limit of the platform. - ]], - params = { - { name = 'name', type = 'string' }, - }, - returns = success_ret, - }, - { - name = 'thread_getname', - method_form = 'thread:getname()', - desc = 'Gets the name of the thread specified by `thread`.', - params = { - { name = 'thread', type = 'luv_thread_t' }, - }, - returns = ret_or_fail('string', 'name'), + For Linux, when schedule policy is SCHED_OTHER (default), priority is 0. + ]], + params = { + { name = 'thread', type = 'luv_thread_t' }, }, - { - name = 'sleep', - desc = [[ - Pauses the thread in which this is called for a number of milliseconds. - ]], - params = { - { name = 'msec', type = 'integer' }, - }, + returns = ret_or_fail('integer', 'priority'), + }, + { + name = 'thread_self', + desc = 'Returns the handle for the thread in which this is called.', + returns = 'luv_thread_t', + }, + { + name = 'thread_join', + method_form = 'thread:join()', + desc = 'Waits for the `thread` to finish executing its entry function.', + params = { + { name = 'thread', type = 'luv_thread_t' }, + }, + returns = ret_or_fail('boolean', 'success'), + }, + { + name = 'thread_detach', + method_form = 'thread:detach()', + desc = [[ + Detaches a thread. Detached threads automatically release their resources upon + termination, eliminating the need for the application to call `uv.thread_join`. + ]], + params = { + { name = 'thread', type = 'luv_thread_t' }, + }, + returns = ret_or_fail('boolean', 'success'), + }, + { + name = 'thread_setname', + desc = [[ + Sets the name of the current thread. Different platforms define different limits + on the max number of characters a thread name can be: Linux, IBM i (16), macOS + (64), Windows (32767), and NetBSD (32), etc. The name will be truncated + if `name` is larger than the limit of the platform. + ]], + params = { + { name = 'name', type = 'string' }, + }, + returns = success_ret, + }, + { + name = 'thread_getname', + method_form = 'thread:getname()', + desc = 'Gets the name of the thread specified by `thread`.', + params = { + { name = 'thread', type = 'luv_thread_t' }, + }, + returns = ret_or_fail('string', 'name'), + }, + { + name = 'sleep', + desc = [[ + Pauses the thread in which this is called for a number of milliseconds. + ]], + params = { + { name = 'msec', type = 'integer' }, }, }, }, - { - title = 'Miscellaneous utilities', - id = 'miscellaneous-utilities', - methods = { - { - name = 'exepath', - desc = 'Returns the executable path.', - returns = ret_or_fail('string', 'path'), - }, - { - name = 'cwd', - desc = 'Returns the current working directory.', - returns = ret_or_fail('string', 'path'), - }, - { - name = 'chdir', - desc = 'Sets the current working directory with the string `cwd`.', - params = { - { name = 'cwd', type = 'string' }, - }, - returns = success_ret, - }, - { - name = 'get_process_title', - desc = 'Returns the title of the current process.', - returns = ret_or_fail('string', 'title'), - }, - { - name = 'set_process_title', - desc = 'Sets the title of the current process with the string `title`.', - params = { - { name = 'title', type = 'string' }, - }, - returns = success_ret, - }, - { - name = 'get_total_memory', - desc = 'Returns the current total system memory in bytes.', - returns = 'number', - }, - { - name = 'get_free_memory', - desc = 'Returns the current free system memory in bytes.', - returns = 'number', - }, - { - name = 'get_constrained_memory', - desc = [[ - Gets the amount of memory available to the process in bytes based on limits - imposed by the OS. If there is no such constraint, or the constraint is unknown, - 0 is returned. Note that it is not unusual for this value to be less than or - greater than the total system memory. - ]], - returns = 'number', - }, - { - name = 'get_available_memory', - desc = [[ - Gets the amount of free memory that is still available to the process (in - bytes). This differs from `uv.get_free_memory()` in that it takes into account - any limits imposed by the OS. If there is no such constraint, or the constraint - is unknown, the amount returned will be identical to `uv.get_free_memory()`. - ]], - returns = 'number', - }, - { - name = 'resident_set_memory', - desc = 'Returns the resident set size (RSS) for the current process.', - returns = ret_or_fail('integer', 'rss'), - }, - { - name = 'getrusage', - desc = 'Returns the resource usage.', - returns = ret_or_fail('getrusage.result', 'rusage'), - }, - { - name = 'getrusage_thread', - desc = [[ - Gets the resource usage measures for the calling thread. - - **Note** Not supported on all platforms. May return `ENOTSUP`. - On macOS and Windows not all fields are set (the unsupported fields are filled - with zeroes). - ]], - returns = ret_or_fail('getrusage.result', 'rusage'), + }, + { + title = 'Miscellaneous utilities', + id = 'miscellaneous-utilities', + funcs = { + { + name = 'exepath', + desc = 'Returns the executable path.', + returns = ret_or_fail('string', 'path'), + }, + { + name = 'cwd', + desc = 'Returns the current working directory.', + returns = ret_or_fail('string', 'path'), + }, + { + name = 'chdir', + desc = 'Sets the current working directory with the string `cwd`.', + params = { + { name = 'cwd', type = 'string' }, }, - { - name = 'available_parallelism', - desc = [[ - Returns an estimate of the default amount of parallelism a program should use. Always returns a non-zero value. + returns = success_ret, + }, + { + name = 'get_process_title', + desc = 'Returns the title of the current process.', + returns = ret_or_fail('string', 'title'), + }, + { + name = 'set_process_title', + desc = 'Sets the title of the current process with the string `title`.', + params = { + { name = 'title', type = 'string' }, + }, + returns = success_ret, + }, + { + name = 'get_total_memory', + desc = 'Returns the current total system memory in bytes.', + returns = 'number', + }, + { + name = 'get_free_memory', + desc = 'Returns the current free system memory in bytes.', + returns = 'number', + }, + { + name = 'get_constrained_memory', + desc = [[ + Gets the amount of memory available to the process in bytes based on limits + imposed by the OS. If there is no such constraint, or the constraint is unknown, + 0 is returned. Note that it is not unusual for this value to be less than or + greater than the total system memory. + ]], + returns = 'number', + }, + { + name = 'get_available_memory', + desc = [[ + Gets the amount of free memory that is still available to the process (in + bytes). This differs from `uv.get_free_memory()` in that it takes into account + any limits imposed by the OS. If there is no such constraint, or the constraint + is unknown, the amount returned will be identical to `uv.get_free_memory()`. + ]], + returns = 'number', + }, + { + name = 'resident_set_memory', + desc = 'Returns the resident set size (RSS) for the current process.', + returns = ret_or_fail('integer', 'rss'), + }, + { + name = 'getrusage', + desc = 'Returns the resource usage.', + returns = ret_or_fail('getrusage.result', 'rusage'), + }, + { + name = 'getrusage_thread', + desc = [[ + Gets the resource usage measures for the calling thread. + + **Note** Not supported on all platforms. May return `ENOTSUP`. + On macOS and Windows not all fields are set (the unsupported fields are filled + with zeroes). + ]], + returns = ret_or_fail('getrusage.result', 'rusage'), + }, + { + name = 'available_parallelism', + desc = [[ + Returns an estimate of the default amount of parallelism a program should use. Always returns a non-zero value. - On Linux, inspects the calling thread’s CPU affinity mask to determine if it has been pinned to specific CPUs. + On Linux, inspects the calling thread’s CPU affinity mask to determine if it has been pinned to specific CPUs. - On Windows, the available parallelism may be underreported on systems with more than 64 logical CPUs. + On Windows, the available parallelism may be underreported on systems with more than 64 logical CPUs. - On other platforms, reports the number of CPUs that the operating system considers to be online. - ]], - returns = 'integer', - }, - { - name = 'cpu_info', - desc = [[ - Returns information about the CPU(s) on the system as a table of tables for each - CPU found. - ]], - returns = ret_or_fail( - dict( - 'integer', - table({ - { 'model', 'string' }, - { 'speed', 'integer' }, - { - 'times', - table({ - { 'user', 'integer' }, - { 'nice', 'integer' }, - { 'sys', 'integer' }, - { 'idle', 'integer' }, - { 'irq', 'integer' }, - }), - }, - }) - ), - 'cpu_info' + On other platforms, reports the number of CPUs that the operating system considers to be online. + ]], + returns = 'integer', + }, + { + name = 'cpu_info', + desc = [[ + Returns information about the CPU(s) on the system as a table of tables for each + CPU found. + ]], + returns = ret_or_fail( + dict( + 'integer', + table({ + { 'model', 'string' }, + { 'speed', 'integer' }, + { + 'times', + table({ + { 'user', 'integer' }, + { 'nice', 'integer' }, + { 'sys', 'integer' }, + { 'idle', 'integer' }, + { 'irq', 'integer' }, + }), + }, + }) ), + 'cpu_info' + ), + }, + { + name = 'cpumask_size', + desc = [[ + Returns the maximum size of the mask used for process/thread affinities, or + `ENOTSUP` if affinities are not supported on the current platform. + ]], + returns = ret_or_fail('integer', 'size'), + }, + { + name = 'getpid', + deprecated = 'Please use `uv.os_getpid()` instead.', + returns = 'integer', + }, + { + name = 'getuid', + desc = 'Returns the user ID of the process.', + returns = 'integer', + notes = { + 'This is not a libuv function and is not supported on Windows.', }, - { - name = 'cpumask_size', - desc = [[ - Returns the maximum size of the mask used for process/thread affinities, or - `ENOTSUP` if affinities are not supported on the current platform. - ]], - returns = ret_or_fail('integer', 'size'), - }, - { - name = 'getpid', - deprecated = 'Please use `uv.os_getpid()` instead.', - returns = 'integer', - }, - { - name = 'getuid', - desc = 'Returns the user ID of the process.', - returns = 'integer', - notes = { - 'This is not a libuv function and is not supported on Windows.', - }, + }, + { + name = 'getgid', + desc = 'Returns the group ID of the process.', + returns = 'integer', + notes = { + 'This is not a libuv function and is not supported on Windows.', }, - { - name = 'getgid', - desc = 'Returns the group ID of the process.', - returns = 'integer', - notes = { - 'This is not a libuv function and is not supported on Windows.', - }, + }, + { + name = 'setuid', + desc = 'Sets the user ID of the process with the integer `id`.', + params = { + { name = 'id', type = 'integer' }, }, - { - name = 'setuid', - desc = 'Sets the user ID of the process with the integer `id`.', - params = { - { name = 'id', type = 'integer' }, - }, - notes = { - 'This is not a libuv function and is not supported on Windows.', - }, + notes = { + 'This is not a libuv function and is not supported on Windows.', }, - { - name = 'setgid', - desc = 'Sets the group ID of the process with the integer `id`.', - params = { - { name = 'id', type = 'integer' }, - }, - notes = { - 'This is not a libuv function and is not supported on Windows.', - }, + }, + { + name = 'setgid', + desc = 'Sets the group ID of the process with the integer `id`.', + params = { + { name = 'id', type = 'integer' }, }, - { - name = 'hrtime', - desc = [[ - Returns a current high-resolution time in nanoseconds as a number. This is - relative to an arbitrary time in the past. It is not related to the time of day - and therefore not subject to clock drift. The primary use is for measuring - time between intervals. - ]], - returns = 'number', + notes = { + 'This is not a libuv function and is not supported on Windows.', }, - { - name = 'clock_gettime', - desc = [[ - Obtain the current system time from a high-resolution real-time or monotonic - clock source. `clock_id` can be the string `"monotonic"` or `"realtime"`. + }, + { + name = 'hrtime', + desc = [[ + Returns a current high-resolution time in nanoseconds as a number. This is + relative to an arbitrary time in the past. It is not related to the time of day + and therefore not subject to clock drift. The primary use is for measuring + time between intervals. + ]], + returns = 'number', + }, + { + name = 'clock_gettime', + desc = [[ + Obtain the current system time from a high-resolution real-time or monotonic + clock source. `clock_id` can be the string `"monotonic"` or `"realtime"`. - The real-time clock counts from the UNIX epoch (1970-01-01) and is subject - to time adjustments; it can jump back in time. + The real-time clock counts from the UNIX epoch (1970-01-01) and is subject + to time adjustments; it can jump back in time. - The monotonic clock counts from an arbitrary point in the past and never - jumps back in time. - ]], - params = { - { name = 'clock_id', type = 'string' }, - }, - returns = ret_or_fail(table({ { 'sec', 'integer' }, { 'nsec', 'integer' } }), 'time'), - }, - { - name = 'uptime', - desc = 'Returns the current system uptime in seconds.', - returns = ret_or_fail('number', 'uptime'), - }, - { - name = 'print_all_handles', - desc = [[ - Prints all handles associated with the main loop to stderr. The format is - `[flags] handle-type handle-address`. Flags are `R` for referenced, `A` for - active and `I` for internal. - ]], - notes = { - 'This is not available on Windows.', - }, - warnings = { - [[ - This function is meant for ad hoc debugging, there are no API/ABI - stability guarantees. - ]], - }, + The monotonic clock counts from an arbitrary point in the past and never + jumps back in time. + ]], + params = { + { name = 'clock_id', type = 'string' }, }, - { - name = 'print_active_handles', - desc = 'The same as `uv.print_all_handles()` except only active handles are printed.', - notes = { - 'This is not available on Windows.', - }, - warnings = { - [[ - This function is meant for ad hoc debugging, there are no API/ABI - stability guarantees. - ]], - }, + returns = ret_or_fail(table({ { 'sec', 'integer' }, { 'nsec', 'integer' } }), 'time'), + }, + { + name = 'uptime', + desc = 'Returns the current system uptime in seconds.', + returns = ret_or_fail('number', 'uptime'), + }, + { + name = 'print_all_handles', + desc = [[ + Prints all handles associated with the main loop to stderr. The format is + `[flags] handle-type handle-address`. Flags are `R` for referenced, `A` for + active and `I` for internal. + ]], + notes = { + 'This is not available on Windows.', }, - { - name = 'guess_handle', - desc = [[ - Used to detect what type of stream should be used with a given file - descriptor `fd`. Usually this will be used during initialization to guess the - type of the stdio streams. + warnings = { + [[ + This function is meant for ad hoc debugging, there are no API/ABI + stability guarantees. ]], - params = { - { name = 'fd', type = 'integer' }, - }, - returns = 'string', }, - { - name = 'gettimeofday', - desc = [[ - Cross-platform implementation of `gettimeofday(2)`. Returns the seconds and - microseconds of a unix time as a pair. - ]], - returns = ret_or_fail('integer, integer', 'second and microseconds'), + }, + { + name = 'print_active_handles', + desc = 'The same as `uv.print_all_handles()` except only active handles are printed.', + notes = { + 'This is not available on Windows.', }, - { - name = 'interface_addresses', - desc = [[ - Returns address information about the network interfaces on the system in a - table. Each table key is the name of the interface while each associated value - is an array of address information where fields are `ip`, `family`, `netmask`, - `internal`, and `mac`. - - See [Constants][] for supported address `family` output values. + warnings = { + [[ + This function is meant for ad hoc debugging, there are no API/ABI + stability guarantees. ]], - returns = { - { - dict( - 'string', - table({ - { 'ip', 'string' }, - { 'family', 'string' }, - { 'netmask', 'string' }, - { 'internal', 'boolean' }, - { 'mac', 'string' }, - }) - ), - 'addresses', - }, - }, }, - { - name = 'if_indextoname', - desc = 'IPv6-capable implementation of `if_indextoname(3)`.', - params = { - { name = 'ifindex', type = 'integer' }, - }, - returns = ret_or_fail('string', 'name'), - }, - { - name = 'if_indextoiid', - desc = [[ - Retrieves a network interface identifier suitable for use in an IPv6 scoped - address. On Windows, returns the numeric `ifindex` as a string. On all other - platforms, `uv.if_indextoname()` is used. - ]], - params = { - { name = 'ifindex', type = 'integer' }, - }, - returns = ret_or_fail('string', 'iid'), + }, + { + name = 'guess_handle', + desc = [[ + Used to detect what type of stream should be used with a given file + descriptor `fd`. Usually this will be used during initialization to guess the + type of the stdio streams. + ]], + params = { + { name = 'fd', type = 'integer' }, }, - { - name = 'loadavg', - desc = 'Returns the load average as a triad. Not supported on Windows.', - returns = 'number, number, number', + returns = 'string', + }, + { + name = 'gettimeofday', + desc = [[ + Cross-platform implementation of `gettimeofday(2)`. Returns the seconds and + microseconds of a unix time as a pair. + ]], + -- returns = ret_or_fail('integer, integer', 'second and microseconds'), + returns = { + { opt_int, 'seconds' }, + { union('integer', 'string'), 'microseconds or err' }, + { opt('uv.error_name'), 'err_name' }, }, - { - name = 'os_uname', - desc = 'Returns system information.', - returns = { - { + returns_doc = '`integer, integer` or `fail`', + }, + { + name = 'interface_addresses', + desc = [[ + Returns address information about the network interfaces on the system in a + table. Each table key is the name of the interface while each associated value + is an array of address information where fields are `ip`, `family`, `netmask`, + `internal`, and `mac`. + + See [Constants][] for supported address `family` output values. + ]], + returns = { + { + dict( + 'string', table({ - { 'sysname', 'string' }, - { 'release', 'string' }, - { 'version', 'string' }, - { 'machine', 'string' }, - }), - 'info', - }, + { 'ip', 'string' }, + { 'family', 'string' }, + { 'netmask', 'string' }, + { 'internal', 'boolean' }, + { 'mac', 'string' }, + }) + ), + 'addresses', }, }, - { - name = 'os_gethostname', - desc = 'Returns the hostname.', - returns = 'string', - }, - { - name = 'os_getenv', - desc = [[ - Returns the environment variable specified by `name` as string. The internal - buffer size can be set by defining `size`. If omitted, `LUAL_BUFFERSIZE` is - used. If the environment variable exceeds the storage available in the internal - buffer, `ENOBUFS` is returned. If no matching environment variable exists, - `ENOENT` is returned. - ]], - params = { - { name = 'name', type = 'string' }, - { name = 'size', type = opt('integer'), default = 'LUA_BUFFERSIZE' }, - }, - returns = ret_or_fail('string', 'value'), - warnings = { 'This function is not thread-safe.' }, - }, - { - name = 'os_setenv', - desc = 'Sets the environmental variable specified by `name` with the string `value`.', - params = { - { name = 'name', type = 'string' }, - { name = 'value', type = 'string' }, - }, - returns = ret_or_fail('boolean', 'success'), - warnings = { - 'This function is not thread-safe.', - }, + }, + { + name = 'if_indextoname', + desc = 'IPv6-capable implementation of `if_indextoname(3)`.', + params = { + { name = 'ifindex', type = 'integer' }, }, - { - name = 'os_unsetenv', - desc = 'Unsets the environmental variable specified by `name`.', - params = { - { name = 'name', type = 'string' }, - }, - returns = ret_or_fail('boolean', 'success'), - warnings = { 'This function is not thread-safe.' }, - }, - { - name = 'os_environ', - desc = [[ - Returns all environmental variables as a dynamic table of names associated with - their corresponding values. - ]], - returns = 'table', - warnings = { 'This function is not thread-safe.' }, - }, - { - name = 'os_homedir', - desc = 'Returns the home directory.', - returns = ret_or_fail('string', 'path'), - warnings = { 'This function is not thread-safe.' }, - }, - { - name = 'os_tmpdir', - desc = 'Returns a temporary directory.', - returns = ret_or_fail('string', 'path'), - warnings = { 'This function is not thread-safe.' }, - }, - { - name = 'os_get_passwd', - desc = 'Returns password file information.', - returns = { - { - table({ - { 'username', 'string' }, - { 'uid', 'integer' }, - { 'gid', 'integer' }, - { 'shell', 'string' }, - { 'homedir', 'string' }, - }), - 'passwd', - }, - }, + returns = ret_or_fail('string', 'name'), + }, + { + name = 'if_indextoiid', + desc = [[ + Retrieves a network interface identifier suitable for use in an IPv6 scoped + address. On Windows, returns the numeric `ifindex` as a string. On all other + platforms, `uv.if_indextoname()` is used. + ]], + params = { + { name = 'ifindex', type = 'integer' }, }, - { - name = 'os_getpid', - desc = 'Returns the current process ID.', - returns = 'number', - }, - { - name = 'os_getppid', - desc = 'Returns the parent process ID.', - returns = 'number', - }, - { - name = 'os_getpriority', - desc = 'Returns the scheduling priority of the process specified by `pid`.', - params = { - { name = 'pid', type = 'integer' }, + returns = ret_or_fail('string', 'iid'), + }, + { + name = 'loadavg', + desc = 'Returns the load average as a triad. Not supported on Windows.', + returns = 'number, number, number', + }, + { + name = 'os_uname', + desc = 'Returns system information.', + returns = { + { + table({ + { 'sysname', 'string' }, + { 'release', 'string' }, + { 'version', 'string' }, + { 'machine', 'string' }, + }), + 'info', }, - returns = ret_or_fail('integer', 'priority'), }, - { - name = 'os_setpriority', - desc = [[ - Sets the scheduling priority of the process specified by `pid`. The `priority` - range is between -20 (high priority) and 19 (low priority). - ]], - params = { - { name = 'pid', type = 'integer' }, - { name = 'priority', type = 'integer' }, - }, - returns = ret_or_fail('boolean', 'success'), - }, - { - name = 'random', - desc = [[ - Fills a string of length `len` with cryptographically strong random bytes - acquired from the system CSPRNG. `flags` is reserved for future extension - and must currently be `nil` or `0` or `{}`. - - Short reads are not possible. When less than `len` random bytes are available, - a non-zero error value is returned or passed to the callback. If the callback - is omitted, this function is completed synchronously. - - The synchronous version may block indefinitely when not enough entropy is - available. The asynchronous version may not ever finish when the system is - low on entropy. - ]], - params = { - { name = 'len', type = 'integer' }, - { name = 'flags', type = opt(union('0', table())) }, - async_cb({ { 'bytes', opt('string') } }), - }, - returns_sync = ret_or_fail('string', 'bytes'), - returns_async = success_ret, + }, + { + name = 'os_gethostname', + desc = 'Returns the hostname.', + returns = 'string', + }, + { + name = 'os_getenv', + desc = [[ + Returns the environment variable specified by `name` as string. The internal + buffer size can be set by defining `size`. If omitted, `LUAL_BUFFERSIZE` is + used. If the environment variable exceeds the storage available in the internal + buffer, `ENOBUFS` is returned. If no matching environment variable exists, + `ENOENT` is returned. + ]], + params = { + { name = 'name', type = 'string' }, + { name = 'size', type = opt_int, default = 'LUA_BUFFERSIZE' }, }, - { - name = 'translate_sys_error', - desc = [[ - Returns the libuv error message and error name (both in string form, see [`err` and `name` in Error Handling](#error-handling)) equivalent to the given platform dependent error code: POSIX error codes on Unix (the ones stored in errno), and Win32 error codes on Windows (those returned by GetLastError() or WSAGetLastError()). - ]], - params = { - { name = 'errcode', type = 'integer' }, - }, - returns = { - { opt('string'), 'message' }, - { opt('string'), 'name' }, - }, - returns_doc = '`string, string` or `nil`', + returns = ret_or_fail('string', 'value'), + warnings = { 'This function is not thread-safe.' }, + }, + { + name = 'os_setenv', + desc = 'Sets the environmental variable specified by `name` with the string `value`.', + params = { + { name = 'name', type = 'string' }, + { name = 'value', type = 'string' }, + }, + returns = ret_or_fail('boolean', 'success'), + warnings = { + 'This function is not thread-safe.', }, }, - }, - { - title = 'Metrics operations', - id = 'metrics-operations', - methods = { - { - name = 'metrics_idle_time', - desc = [[ - Retrieve the amount of time the event loop has been idle in the kernel’s event - provider (e.g. `epoll_wait`). The call is thread safe. - - The return value is the accumulated time spent idle in the kernel’s event - provider starting from when the [`uv_loop_t`][] was configured to collect the idle time. - - **Note:** The event loop will not begin accumulating the event provider’s idle - time until calling `loop_configure` with `"metrics_idle_time"`. - ]], - returns = 'number', - }, - { - name = 'metrics_info', - desc = [[ - Get the metrics table from current set of event loop metrics. It is recommended - to retrieve these metrics in a `prepare` callback (see `uv.new_prepare`, - `uv.prepare_start`) in order to make sure there are no inconsistencies with the - metrics counters. - ]], - returns = { - { - table({ - { 'loop_count', 'number' }, - { 'events', 'integer' }, - { 'events_waiting', 'number' }, - }), - 'info', - }, + { + name = 'os_unsetenv', + desc = 'Unsets the environmental variable specified by `name`.', + params = { + { name = 'name', type = 'string' }, + }, + returns = ret_or_fail('boolean', 'success'), + warnings = { 'This function is not thread-safe.' }, + }, + { + name = 'os_environ', + desc = [[ + Returns all environmental variables as a dynamic table of names associated with + their corresponding values. + ]], + returns = 'table', + warnings = { 'This function is not thread-safe.' }, + }, + { + name = 'os_homedir', + desc = 'Returns the home directory.', + returns = ret_or_fail('string', 'path'), + warnings = { 'This function is not thread-safe.' }, + }, + { + name = 'os_tmpdir', + desc = 'Returns a temporary directory.', + returns = ret_or_fail('string', 'path'), + warnings = { 'This function is not thread-safe.' }, + }, + { + name = 'os_get_passwd', + desc = 'Returns password file information.', + returns = { + { + table({ + { 'username', 'string' }, + { 'uid', 'integer' }, + { 'gid', 'integer' }, + { 'shell', 'string' }, + { 'homedir', 'string' }, + }), + 'passwd', }, }, }, - }, - { - title = 'String manipulation functions', - desc = [[ - These string utilities are needed internally for dealing with Windows, and are exported to allow clients to work uniformly with this data when the libuv API is not complete. - - **Notes**: - - 1. New in luv version 1.49.0. - 2. See [the WTF-8 spec](https://simonsapin.github.io/wtf-8/) for information about WTF-8. - 3. Luv uses Lua-style strings, which means that all inputs and return values (UTF-8 or UTF-16 strings) do not include a NUL terminator. - ]], - methods = { - { - name = 'utf16_length_as_wtf8', - desc = 'Get the length (in bytes) of a UTF-16 (or UCS-2) string `utf16` value after converting it to WTF-8.', - params = { - { name = 'utf16', type = 'string' }, - }, - returns = 'integer', + { + name = 'os_getpid', + desc = 'Returns the current process ID.', + returns = 'number', + }, + { + name = 'os_getppid', + desc = 'Returns the parent process ID.', + returns = 'number', + }, + { + name = 'os_getpriority', + desc = 'Returns the scheduling priority of the process specified by `pid`.', + params = { + { name = 'pid', type = 'integer' }, }, - { - name = 'utf16_to_wtf8', - desc = [[ - Convert UTF-16 (or UCS-2) string `utf16` to WTF-8 string. The endianness of the UTF-16 (or UCS-2) string is assumed to be the same as the native endianness of the platform. - ]], - params = { - { name = 'utf16', type = 'string' }, - }, - returns = 'string', + returns = ret_or_fail('integer', 'priority'), + }, + { + name = 'os_setpriority', + desc = [[ + Sets the scheduling priority of the process specified by `pid`. The `priority` + range is between -20 (high priority) and 19 (low priority). + ]], + params = { + { name = 'pid', type = 'integer' }, + { name = 'priority', type = 'integer' }, }, - { - name = 'wtf8_length_as_utf16', - desc = [[ - Get the length (in UTF-16 code units) of a WTF-8 `wtf8` value after converting it to UTF-16 (or UCS-2). Note: The number of bytes needed for a UTF-16 (or UCS-2) string is ` * 2`. - ]], - params = { - { name = 'wtf8', type = 'string' }, - }, - returns = 'integer', + returns = ret_or_fail('boolean', 'success'), + }, + { + name = 'random', + desc = [[ + Fills a string of length `len` with cryptographically strong random bytes + acquired from the system CSPRNG. `flags` is reserved for future extension + and must currently be `nil` or `0` or `{}`. + + Short reads are not possible. When less than `len` random bytes are available, + a non-zero error value is returned or passed to the callback. If the callback + is omitted, this function is completed synchronously. + + The synchronous version may block indefinitely when not enough entropy is + available. The asynchronous version may not ever finish when the system is + low on entropy. + ]], + params = { + { name = 'len', type = 'integer' }, + { name = 'flags', type = opt(union('0', table())) }, + async_cb({ { 'bytes', opt_str } }), }, - { - name = 'wtf8_to_utf16', - desc = [[ - Convert WTF-8 string in `wtf8` to UTF-16 (or UCS-2) string. The endianness of the UTF-16 (or UCS-2) string will be the same as the native endianness of the platform. - ]], - params = { - { name = 'wtf8', type = 'string' }, + returns_sync = ret_or_fail('string', 'bytes'), + returns_async = success_ret, + }, + { + name = 'translate_sys_error', + desc = [[ + Returns the libuv error message and error name (both in string form, see [`err` and `name` in Error Handling](#error-handling)) equivalent to the given platform dependent error code: POSIX error codes on Unix (the ones stored in errno), and Win32 error codes on Windows (those returned by GetLastError() or WSAGetLastError()). + ]], + params = { + { name = 'errcode', type = 'integer' }, + }, + returns = { + { opt_str, 'message' }, + { opt_str, 'name' }, + }, + returns_doc = '`string, string` or `nil`', + }, + }, + }, + { + title = 'Metrics operations', + id = 'metrics-operations', + funcs = { + { + name = 'metrics_idle_time', + desc = [[ + Retrieve the amount of time the event loop has been idle in the kernel’s event + provider (e.g. `epoll_wait`). The call is thread safe. + + The return value is the accumulated time spent idle in the kernel’s event + provider starting from when the [`uv_loop_t`][] was configured to collect the idle time. + + **Note:** The event loop will not begin accumulating the event provider’s idle + time until calling `loop_configure` with `"metrics_idle_time"`. + ]], + returns = 'number', + }, + { + name = 'metrics_info', + desc = [[ + Get the metrics table from current set of event loop metrics. It is recommended + to retrieve these metrics in a `prepare` callback (see `uv.new_prepare`, + `uv.prepare_start`) in order to make sure there are no inconsistencies with the + metrics counters. + ]], + returns = { + { + table({ + { 'loop_count', 'number' }, + { 'events', 'integer' }, + { 'events_waiting', 'number' }, + }), + 'info', }, - returns = 'string', }, }, }, - { -- links - desc = [[ - --- - - [luv]: https://github.com/luvit/luv - [luvit]: https://github.com/luvit/luvit - [libuv]: https://github.com/libuv/libuv - [libuv documentation page]: http://docs.libuv.org/ - [libuv API documentation]: http://docs.libuv.org/en/v1.x/api.html - [error constants]: https://docs.libuv.org/en/v1.x/errors.html#error-constants - ]], + }, + { + title = 'String manipulation functions', + desc = [[ + These string utilities are needed internally for dealing with Windows, and are exported to allow clients to work uniformly with this data when the libuv API is not complete. + + **Notes**: + + 1. New in luv version 1.49.0. + 2. See [the WTF-8 spec](https://simonsapin.github.io/wtf-8/) for information about WTF-8. + 3. Luv uses Lua-style strings, which means that all inputs and return values (UTF-8 or UTF-16 strings) do not include a NUL terminator. + ]], + funcs = { + { + name = 'utf16_length_as_wtf8', + desc = 'Get the length (in bytes) of a UTF-16 (or UCS-2) string `utf16` value after converting it to WTF-8.', + params = { + { name = 'utf16', type = 'string' }, + }, + returns = 'integer', + }, + { + name = 'utf16_to_wtf8', + desc = [[ + Convert UTF-16 (or UCS-2) string `utf16` to WTF-8 string. The endianness of the UTF-16 (or UCS-2) string is assumed to be the same as the native endianness of the platform. + ]], + params = { + { name = 'utf16', type = 'string' }, + }, + returns = 'string', + }, + { + name = 'wtf8_length_as_utf16', + desc = [[ + Get the length (in UTF-16 code units) of a WTF-8 `wtf8` value after converting it to UTF-16 (or UCS-2). Note: The number of bytes needed for a UTF-16 (or UCS-2) string is ` * 2`. + ]], + params = { + { name = 'wtf8', type = 'string' }, + }, + returns = 'integer', + }, + { + name = 'wtf8_to_utf16', + desc = [[ + Convert WTF-8 string in `wtf8` to UTF-16 (or UCS-2) string. The endianness of the UTF-16 (or UCS-2) string will be the same as the native endianness of the platform. + ]], + params = { + { name = 'wtf8', type = 'string' }, + }, + returns = 'string', + }, }, }, + { -- links + desc = [[ + --- + + [luv]: https://github.com/luvit/luv + [luvit]: https://github.com/luvit/luvit + [libuv]: https://github.com/libuv/libuv + [libuv documentation page]: http://docs.libuv.org/ + [libuv API documentation]: http://docs.libuv.org/en/v1.x/api.html + [error constants]: https://docs.libuv.org/en/v1.x/errors.html#error-constants + ]], + }, }, } diff --git a/docs.md b/docs.md index 10914d8e..bd9d5126 100644 --- a/docs.md +++ b/docs.md @@ -1272,7 +1272,49 @@ a better job on Windows than it does on Unix. **Parameters:** - `path`: `string` -- `options`: `table` (see below) +- `options`: `table` + - `args`: `string[]` or `nil` + Command line arguments as a list of strings. The first + string should *not* be the path to the program, since that is already + provided via `path`. On Windows, this uses CreateProcess which concatenates + the arguments into a string. This can cause some strange errors + (see `options.verbatim` below for Windows). + - `stdio`: `table` or `nil` + Set the file descriptors that will be made available to + the child process. The convention is that the first entries are stdin, stdout, + and stderr. + + The entries can take many shapes. + - If `integer`, then the child process inherits that same zero-indexed + fd from the parent process. + - If `uv_stream_t` handles are passed in, those are used as a read-write pipe + or inherited stream depending if the stream has a valid fd. + - If `nil`, means to ignore that fd in the child process. + + **Note**: On Windows, file descriptors after the third are + available to the child process only if the child processes uses the MSVCRT + runtime. + - `[1, 2, 3, ..., n]`: `integer` or `userdata` for sub-type of `uv_stream_t` or `nil` + - `env`: `table` or `nil` Set environment variables for the new process. + - `[string]`: `string` + - `cwd`: `string` or `nil` Set the current working directory for the sub-process. + - `uid`: `string` or `nil` Set the child process' user id. + - `gid`: `string` or `nil` Set the child process' group id. + - `verbatim`: `boolean` or `nil` + If true, do not wrap any arguments in quotes, or + perform any other escaping, when converting the argument list into a command + line string. This option is only meaningful on Windows systems. On Unix it is + silently ignored. + - `detached`: `boolean` or `nil` + If true, spawn the child process in a detached state - + this will make it a process group leader, and will effectively enable the + child to keep running after the parent exits. Note that the child process + will still keep the parent's event loop alive unless the parent process calls + `uv.unref()` on the child's process handle. + - `hide`: `boolean` or `nil` + If true, hide the subprocess console window that would + normally be created. This option is only meaningful on Windows systems. On + Unix it is silently ignored. - `on_exit`: `callable` - `code`: `integer` - `signal`: `integer` @@ -1331,43 +1373,6 @@ uv.shutdown(stdin, function() end) ``` -The `options` table accepts the following fields: - - - `options.args` - Command line arguments as a list of strings. The first - string should *not* be the path to the program, since that is already - provided via `path`. On Windows, this uses CreateProcess which concatenates - the arguments into a string. This can cause some strange errors - (see `options.verbatim` below for Windows). - - `options.stdio` - Set the file descriptors that will be made available to - the child process. The convention is that the first entries are stdin, stdout, - and stderr. (**Note**: On Windows, file descriptors after the third are - available to the child process only if the child processes uses the MSVCRT - runtime.) - - `options.env` - Set environment variables for the new process. - - `options.cwd` - Set the current working directory for the sub-process. - - `options.uid` - Set the child process' user id. - - `options.gid` - Set the child process' group id. - - `options.verbatim` - If true, do not wrap any arguments in quotes, or - perform any other escaping, when converting the argument list into a command - line string. This option is only meaningful on Windows systems. On Unix it is - silently ignored. - - `options.detached` - If true, spawn the child process in a detached state - - this will make it a process group leader, and will effectively enable the - child to keep running after the parent exits. Note that the child process - will still keep the parent's event loop alive unless the parent process calls - `uv.unref()` on the child's process handle. - - `options.hide` - If true, hide the subprocess console window that would - normally be created. This option is only meaningful on Windows systems. On - Unix it is silently ignored. - -The `options.stdio` entries can take many shapes. - - - If they are numbers, then the child process inherits that same zero-indexed - fd from the parent process. - - If `uv_stream_t` handles are passed in, those are used as a read-write pipe - or inherited stream depending if the stream has a valid fd. - - Including `nil` placeholders means to ignore that fd in the child process. - When the child process exits, `on_exit` is called with an exit code and signal. **Returns:** `uv_process_t userdata`, `integer` @@ -1632,10 +1637,13 @@ when the blocking mode is changed after write requests have already been submitted. Therefore it is recommended to set the blocking mode immediately after opening or creating the stream. -### `uv.stream_get_write_queue_size()` +### `uv.stream_get_write_queue_size(stream)` > method form `stream:get_write_queue_size()` +**Parameters:** +- `stream`: `userdata` for sub-type of `uv_stream_t` + Returns the stream's write queue size. **Returns:** `integer` @@ -2245,18 +2253,24 @@ calling `uv_udp_init_ex`. **Returns:** `uv_udp_t userdata` or `fail` -### `uv.udp_get_send_queue_size()` +### `uv.udp_get_send_queue_size(udp)` > method form `udp:get_send_queue_size()` +**Parameters:** +- `udp`: `uv_udp_t userdata` + Returns the handle's send queue size. **Returns:** `integer` -### `uv.udp_get_send_queue_count()` +### `uv.udp_get_send_queue_count(udp)` > method form `udp:get_send_queue_count()` +**Parameters:** +- `udp`: `uv_udp_t userdata` + Returns the handle's send queue count. **Returns:** `integer` @@ -2600,18 +2614,24 @@ for changes. **Returns:** `0` or `fail` -### `uv.fs_event_stop()` +### `uv.fs_event_stop(fs_event)` > method form `fs_event:stop()` +**Parameters:** +- `fs_event`: `uv_fs_event_t userdata` + Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` -### `uv.fs_event_getpath()` +### `uv.fs_event_getpath(fs_event)` > method form `fs_event:getpath()` +**Parameters:** +- `fs_event`: `uv_fs_event_t userdata` + Get the path being monitored by the handle. **Returns:** `string` or `fail` @@ -2653,18 +2673,24 @@ intervals will not detect all changes on many file systems. **Returns:** `0` or `fail` -### `uv.fs_poll_stop()` +### `uv.fs_poll_stop(fs_poll)` > method form `fs_poll:stop()` +**Parameters:** +- `fs_poll`: `uv_fs_poll_t userdata` + Stop the handle, the callback will no longer be called. **Returns:** `0` or `fail` -### `uv.fs_poll_getpath()` +### `uv.fs_poll_getpath(fs_poll)` > method form `fs_poll:getpath()` +**Parameters:** +- `fs_poll`: `uv_fs_poll_t userdata` + Get the path being monitored by the handle. **Returns:** `string` or `fail` diff --git a/meta.lua b/meta.lua new file mode 100644 index 00000000..46672c49 --- /dev/null +++ b/meta.lua @@ -0,0 +1,4448 @@ +--- @meta +--- @class uv +local uv = {} +uv.constants = {} + +--- # LibUV in Lua +--- +--- The [luv][] project provides access to the multi-platform support library +--- [libuv][] in Lua code. It was primarily developed for the [luvit][] project as +--- the built-in `uv` module, but can be used in other Lua environments. +--- +--- More information about the core libuv library can be found at the original +--- [libuv documentation page][]. + + +--- # TCP Echo Server Example +--- +--- Here is a small example showing a TCP echo server: +--- +--- ```lua +--- local uv = require("luv") -- "luv" when stand-alone, "uv" in luvi apps +--- +--- local server = uv.new_tcp() +--- server:bind("127.0.0.1", 1337) +--- server:listen(128, function (err) +--- assert(not err, err) +--- local client = uv.new_tcp() +--- server:accept(client) +--- client:read_start(function (err, chunk) +--- assert(not err, err) +--- if chunk then +--- client:write(chunk) +--- else +--- client:shutdown() +--- client:close() +--- end +--- end) +--- end) +--- print("TCP server listening at 127.0.0.1 port 1337") +--- uv.run() -- an explicit run call is necessary outside of luvit +--- ``` + +--- # Module Layout +--- +--- The luv library contains a single Lua module referred to hereafter as `uv` for +--- simplicity. This module consists mostly of functions with names corresponding to +--- their original libuv versions. For example, the libuv function `uv_tcp_bind` has +--- a luv version at `uv.tcp_bind`. Currently, only two non-function fields exists: +--- `uv.constants` and `uv.errno`, which are tables. + +--- # Functions vs Methods +--- +--- In addition to having simple functions, luv provides an optional method-style +--- API. For example, `uv.tcp_bind(server, host, port)` can alternatively be called +--- as `server:bind(host, port)`. Note that the first argument `server` becomes the +--- object and `tcp_` is removed from the function name. Method forms are +--- documented below where they exist. + +--- # Synchronous vs Asynchronous Functions +--- +--- Functions that accept a callback are asynchronous. These functions may +--- immediately return results to the caller to indicate their initial status, but +--- their final execution is deferred until at least the next libuv loop iteration. +--- After completion, their callbacks are executed with any results passed to it. +--- +--- Functions that do not accept a callback are synchronous. These functions +--- immediately return their results to the caller. +--- +--- Some (generally FS and DNS) functions can behave either synchronously or +--- asynchronously. If a callback is provided to these functions, they behave +--- asynchronously; if no callback is provided, they behave synchronously. + +--- # Pseudo-Types +--- +--- Some unique types are defined. These are not actual types in Lua, but they are +--- used here to facilitate documenting consistent behavior: +--- - `fail`: an assertable `nil, string, string` tuple (see [Error Handling][]) +--- - `callable`: a `function`; or a `table` or `userdata` with a `__call` +--- metamethod +--- - `buffer`: a `string` or a sequential `table` of `string`s +--- - `threadargs`: variable arguments (`...`) of type `nil`, `boolean`, `number`, +--- `string`, or `userdata`, numbers of argument limited to 9. + + +--- # Contents +--- +--- This documentation is mostly a retelling of the [libuv API documentation][] +--- within the context of luv's Lua API. Low-level implementation details and +--- unexposed C functions and types are not documented here except for when they +--- are relevant to behavior seen in the Lua module. +--- +--- - [Constants][] +--- - [Error Handling][] +--- - [Version Checking][] +--- - [`uv_loop_t`][] — Event loop +--- - [`uv_req_t`][] — Base request +--- - [`uv_handle_t`][] — Base handle +--- - [`uv_timer_t`][] — Timer handle +--- - [`uv_prepare_t`][] — Prepare handle +--- - [`uv_check_t`][] — Check handle +--- - [`uv_idle_t`][] — Idle handle +--- - [`uv_async_t`][] — Async handle +--- - [`uv_poll_t`][] — Poll handle +--- - [`uv_signal_t`][] — Signal handle +--- - [`uv_process_t`][] — Process handle +--- - [`uv_stream_t`][] — Stream handle +--- - [`uv_tcp_t`][] — TCP handle +--- - [`uv_pipe_t`][] — Pipe handle +--- - [`uv_tty_t`][] — TTY handle +--- - [`uv_udp_t`][] — UDP handle +--- - [`uv_fs_event_t`][] — FS Event handle +--- - [`uv_fs_poll_t`][] — FS Poll handle +--- - [File system operations][] +--- - [Thread pool work scheduling][] +--- - [DNS utility functions][] +--- - [Threading and synchronization utilities][] +--- - [Miscellaneous utilities][] +--- - [Metrics operations][] + +--- # Constants +--- +--- As a Lua library, luv supports and encourages the use of lowercase strings to +--- represent options. For example: +--- ```lua +--- -- signal start with string input +--- uv.signal_start("sigterm", function(signame) +--- print(signame) -- string output: "sigterm" +--- end) +--- ``` +--- +--- However, luv also superficially exposes libuv constants in a Lua table at +--- `uv.constants` where its keys are uppercase constant names and their associated +--- values are integers defined internally by libuv. The values from this table may +--- be supported as function arguments, but their use may not change the output +--- type. For example: +--- +--- ```lua +--- -- signal start with integer input +--- uv.signal_start(uv.constants.SIGTERM, function(signame) +--- print(signame) -- string output: "sigterm" +--- end) +--- ``` +--- +--- The uppercase constants defined in `uv.constants` that have associated +--- lowercase option strings are listed below. + +--- # Address Families +uv.constants.AF_UNIX = 'unix' +uv.constants.AF_INET = 'inet' +uv.constants.AF_INET6 = 'inet6' +uv.constants.AF_IPX = 'ipx' +uv.constants.AF_NETLINK = 'netlink' +uv.constants.AF_X25 = 'x25' +uv.constants.AF_AX25 = 'as25' +uv.constants.AF_ATMPVC = 'atmpvc' +uv.constants.AF_APPLETALK = 'appletalk' +uv.constants.AF_PACKET = 'packet' + +--- # Signals +uv.constants.SIGHUP = 'sighup' +uv.constants.SIGINT = 'sigint' +uv.constants.SIGQUIT = 'sigquit' +uv.constants.SIGILL = 'sigill' +uv.constants.SIGTRAP = 'sigtrap' +uv.constants.SIGABRT = 'sigabrt' +uv.constants.SIGIOT = 'sigiot' +uv.constants.SIGBUS = 'sigbus' +uv.constants.SIGFPE = 'sigfpe' +uv.constants.SIGKILL = 'sigkill' +uv.constants.SIGUSR1 = 'sigusr1' +uv.constants.SIGSEGV = 'sigsegv' +uv.constants.SIGUSR2 = 'sigusr2' +uv.constants.SIGPIPE = 'sigpipe' +uv.constants.SIGALRM = 'sigalrm' +uv.constants.SIGTERM = 'sigterm' +uv.constants.SIGCHLD = 'sigchld' +uv.constants.SIGSTKFLT = 'sigstkflt' +uv.constants.SIGCONT = 'sigcont' +uv.constants.SIGSTOP = 'sigstop' +uv.constants.SIGTSTP = 'sigtstp' +uv.constants.SIGBREAK = 'sigbreak' +uv.constants.SIGTTIN = 'sigttin' +uv.constants.SIGTTOU = 'sigttou' +uv.constants.SIGURG = 'sigurg' +uv.constants.SIGXCPU = 'sigxcpu' +uv.constants.SIGXFSZ = 'sigxfsz' +uv.constants.SIGVTALRM = 'sigvtalrm' +uv.constants.SIGPROF = 'sigprof' +uv.constants.SIGWINCH = 'sigwinch' +uv.constants.SIGIO = 'sigio' +uv.constants.SIGPOLL = 'sigpoll' +uv.constants.SIGLOST = 'siglost' +uv.constants.SIGPWR = 'sigpwr' +uv.constants.SIGSYS = 'sigsys' + +--- # Socket Types +uv.constants.SOCK_STREAM = 'stream' +uv.constants.SOCK_DGRAM = 'dgram' +uv.constants.SOCK_SEQPACKET = 'seqpacket' +uv.constants.SOCK_RAW = 'raw' +uv.constants.SOCK_RDM = 'rdm' + +--- # TTY Modes +uv.constants.TTY_MODE_NORMAL = 'normal' +uv.constants.TTY_MODE_RAW = 'raw' +uv.constants.TTY_MODE_IO = 'io' + + +--- # Error Handling +--- +--- In libuv, errors are represented by negative numbered constants. While these +--- constants are made available in the `uv.errno` table, they are not returned by +--- luv functions and the libuv functions used to handle them are not exposed. +--- Instead, if an internal error is encountered, the failing luv function will +--- return to the caller an assertable `nil, err, name` tuple: +--- +--- - `nil` idiomatically indicates failure +--- - `err` is a string with the format `{name}: {message}` +--- - `{name}` is the error name provided internally by `uv_err_name` +--- - `{message}` is a human-readable message provided internally by `uv_strerror` +--- - `name` is the same string used to construct `err` +--- +--- This tuple is referred to below as the `fail` pseudo-type. +--- +--- When a function is called successfully, it will return either a value that is +--- relevant to the operation of the function, or the integer `0` to indicate +--- success, or sometimes nothing at all. These cases are documented below. +--- +--- Below is a list of known error names and error strings. See libuv's +--- [error constants][] page for an original source. + +--- @alias uv.error_name +--- | 'E2BIG' # argument list too long. +--- | 'EACCES' # permission denied. +--- | 'EADDRINUSE' # address already in use. +--- | 'EADDRNOTAVAIL' # address not available. +--- | 'EAFNOSUPPORT' # address family not supported. +--- | 'EAGAIN' # resource temporarily unavailable. +--- | 'EAI_ADDRFAMILY' # address family not supported. +--- | 'EAI_AGAIN' # temporary failure. +--- | 'EAI_BADFLAGS' # bad ai_flags value. +--- | 'EAI_BADHINTS' # invalid value for hints. +--- | 'EAI_CANCELED' # request canceled. +--- | 'EAI_FAIL' # permanent failure. +--- | 'EAI_FAMILY' # ai_family not supported. +--- | 'EAI_MEMORY' # out of memory. +--- | 'EAI_NODATA' # no address. +--- | 'EAI_NONAME' # unknown node or service. +--- | 'EAI_OVERFLOW' # argument buffer overflow. +--- | 'EAI_PROTOCOL' # resolved protocol is unknown. +--- | 'EAI_SERVICE' # service not available for socket type. +--- | 'EAI_SOCKTYPE' # socket type not supported. +--- | 'EALREADY' # connection already in progress. +--- | 'EBADF' # bad file descriptor. +--- | 'EBUSY' # resource busy or locked. +--- | 'ECANCELED' # operation canceled. +--- | 'ECHARSET' # invalid Unicode character. +--- | 'ECONNABORTED' # software caused connection abort. +--- | 'ECONNREFUSED' # connection refused. +--- | 'ECONNRESET' # connection reset by peer. +--- | 'EDESTADDRREQ' # destination address required. +--- | 'EEXIST' # file already exists. +--- | 'EFAULT' # bad address in system call argument. +--- | 'EFBIG' # file too large. +--- | 'EHOSTUNREACH' # host is unreachable. +--- | 'EINTR' # interrupted system call. +--- | 'EINVAL' # invalid argument. +--- | 'EIO' # i/o error. +--- | 'EISCONN' # socket is already connected. +--- | 'EISDIR' # illegal operation on a directory. +--- | 'ELOOP' # too many symbolic links encountered. +--- | 'EMFILE' # too many open files. +--- | 'EMSGSIZE' # message too long. +--- | 'ENAMETOOLONG' # name too long. +--- | 'ENETDOWN' # network is down. +--- | 'ENETUNREACH' # network is unreachable. +--- | 'ENFILE' # file table overflow. +--- | 'ENOBUFS' # no buffer space available. +--- | 'ENODEV' # no such device. +--- | 'ENOENT' # no such file or directory. +--- | 'ENOMEM' # not enough memory. +--- | 'ENONET' # machine is not on the network. +--- | 'ENOPROTOOPT' # protocol not available. +--- | 'ENOSPC' # no space left on device. +--- | 'ENOSYS' # function not implemented. +--- | 'ENOTCONN' # socket is not connected. +--- | 'ENOTDIR' # not a directory. +--- | 'ENOTEMPTY' # directory not empty. +--- | 'ENOTSOCK' # socket operation on non-socket. +--- | 'ENOTSUP' # operation not supported on socket. +--- | 'EOVERFLOW' # value too large for defined data type. +--- | 'EPERM' # operation not permitted. +--- | 'EPIPE' # broken pipe. +--- | 'EPROTO' # protocol error. +--- | 'EPROTONOSUPPORT' # protocol not supported. +--- | 'EPROTOTYPE' # protocol wrong type for socket. +--- | 'ERANGE' # result too large. +--- | 'EROFS' # read-only file system. +--- | 'ESHUTDOWN' # cannot send after transport endpoint shutdown. +--- | 'ESPIPE' # invalid seek. +--- | 'ESRCH' # no such process. +--- | 'ETIMEDOUT' # connection timed out. +--- | 'ETXTBSY' # text file is busy. +--- | 'EXDEV' # cross-device link not permitted. +--- | 'UNKNOWN' # unknown error. +--- | 'EOF' # end of file. +--- | 'ENXIO' # no such device or address. +--- | 'EMLINK' # too many links. +--- | 'ENOTTY' # inappropriate ioctl for device. +--- | 'EFTYPE' # inappropriate file type or format. +--- | 'EILSEQ' # illegal byte sequence. +--- | 'ESOCKTNOSUPPORT' # socket type not supported. + +--- # Version Checking + +--- Returns the libuv version packed into a single integer. 8 bits are used for each +--- component, with the patch number stored in the 8 least significant bits. For +--- example, this would be 0x010203 in libuv 1.2.3. +--- @return integer +function uv.version() end + +--- Returns the libuv version number as a string. For example, this would be "1.2.3" +--- in libuv 1.2.3. For non-release versions, the version suffix is included. +--- @return string +function uv.version_string() end + + +--- # `uv_loop_t` - Event loop +--- +--- The event loop is the central part of libuv's functionality. It takes care of +--- polling for I/O and scheduling callbacks to be run based on different sources of +--- events. +--- +--- In luv, there is an implicit uv loop for every Lua state that loads the library. +--- You can use this library in an multi-threaded environment as long as each thread +--- has it's own Lua state with its corresponding own uv loop. This loop is not +--- directly exposed to users in the Lua module. + +--- Closes all internal loop resources. In normal execution, the loop will +--- automatically be closed when it is garbage collected by Lua, so it is not +--- necessary to explicitly call `loop_close()`. Call this function only after the +--- loop has finished executing and all open handles and requests have been closed, +--- or it will return `EBUSY`. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.loop_close() end + +--- This function runs the event loop. It will act differently depending on the +--- specified mode: +--- +--- - `"default"`: Runs the event loop until there are no more active and +--- referenced handles or requests. Returns `true` if `uv.stop()` was called and +--- there are still active handles or requests. Returns `false` in all other +--- cases. +--- +--- - `"once"`: Poll for I/O once. Note that this function blocks if there are no +--- pending callbacks. Returns `false` when done (no active handles or requests +--- left), or `true` if more callbacks are expected (meaning you should run the +--- event loop again sometime in the future). +--- +--- - `"nowait"`: Poll for I/O once but don't block if there are no pending +--- callbacks. Returns `false` if done (no active handles or requests left), +--- or `true` if more callbacks are expected (meaning you should run the event +--- loop again sometime in the future). +--- **Note**: +--- Luvit will implicitly call `uv.run()` after loading user code, but if +--- you use the luv bindings directly, you need to call this after registering +--- your initial set of event callbacks to start the event loop. +--- @param mode string? +--- @return boolean? running +--- @return string? err +--- @return uv.error_name? err_name +function uv.run(mode) end + +--- Set additional loop options. You should normally call this before the first call +--- to uv_run() unless mentioned otherwise. +--- +--- Supported options: +--- +--- - `"block_signal"`: Block a signal when polling for new events. The second argument +--- to loop_configure() is the signal name (as a lowercase string) or the signal number. +--- This operation is currently only implemented for `"sigprof"` signals, to suppress +--- unnecessary wakeups when using a sampling profiler. Requesting other signals will +--- fail with `EINVAL`. +--- - `"metrics_idle_time"`: Accumulate the amount of idle time the event loop spends +--- in the event provider. This option is necessary to use `metrics_idle_time()`. +--- +--- An example of a valid call to this function is: +--- +--- ```lua +--- uv.loop_configure("block_signal", "sigprof") +--- ``` +--- **Note**: +--- Be prepared to handle the `ENOSYS` error; it means the loop option is +--- not supported by the platform. +--- @param option string +--- @param ... any depends on `option` +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.loop_configure(option, ...) end + +--- If the loop is running, returns a string indicating the mode in use. If the loop +--- is not running, `nil` is returned instead. +--- @return string? +function uv.loop_mode() end + +--- Returns `true` if there are referenced active handles, active requests, or +--- closing handles in the loop; otherwise, `false`. +--- @return boolean? alive +--- @return string? err +--- @return uv.error_name? err_name +function uv.loop_alive() end + +--- Stop the event loop, causing `uv.run()` to end as soon as possible. This +--- will happen not sooner than the next loop iteration. If this function was called +--- before blocking for I/O, the loop won't block for I/O on this iteration. +function uv.stop() end + +--- Get backend file descriptor. Only kqueue, epoll, and event ports are supported. +--- +--- This can be used in conjunction with `uv.run("nowait")` to poll in one thread +--- and run the event loop's callbacks in another +--- **Note**: +--- Embedding a kqueue fd in another kqueue pollset doesn't work on all +--- platforms. It's not an error to add the fd but it never generates events. +--- @return integer? +function uv.backend_fd() end + +--- Get the poll timeout. The return value is in milliseconds, or -1 for no timeout. +--- @return integer +function uv.backend_timeout() end + +--- Returns the current timestamp in milliseconds. The timestamp is cached at the +--- start of the event loop tick, see `uv.update_time()` for details and rationale. +--- +--- The timestamp increases monotonically from some arbitrary point in time. Don't +--- make assumptions about the starting point, you will only get disappointed. +--- **Note**: +--- Use `uv.hrtime()` if you need sub-millisecond granularity. +--- @return integer +function uv.now() end + +--- Update the event loop's concept of "now". Libuv caches the current time at the +--- start of the event loop tick in order to reduce the number of time-related +--- system calls. +--- +--- You won't normally need to call this function unless you have callbacks that +--- block the event loop for longer periods of time, where "longer" is somewhat +--- subjective but probably on the order of a millisecond or more. +function uv.update_time() end + +--- Walk the list of handles: `callback` will be executed with each handle. +--- Example +--- ```lua +--- -- Example usage of uv.walk to close all handles that aren't already closing. +--- uv.walk(function (handle) +--- if not handle:is_closing() then +--- handle:close() +--- end +--- end) +--- ``` +--- @param callback fun(handle: uv.uv_handle_t) +function uv.walk(callback) end + + +--- # `uv_req_t` - Base request +--- +--- `uv_req_t` is the base type for all libuv request types. +--- @class uv.uv_req_t : userdata +local uv_req_t = {} + +--- Cancel a pending request. Fails if the request is executing or has finished +--- executing. Only cancellation of `uv_fs_t`, `uv_getaddrinfo_t`, +--- `uv_getnameinfo_t` and `uv_work_t` requests is currently supported. +--- @param req uv.uv_req_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.cancel(req) end + +--- Cancel a pending request. Fails if the request is executing or has finished +--- executing. Only cancellation of `uv_fs_t`, `uv_getaddrinfo_t`, +--- `uv_getnameinfo_t` and `uv_work_t` requests is currently supported. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_req_t:cancel() end + +--- Returns the name of the struct for a given request (e.g. `"fs"` for `uv_fs_t`) +--- and the libuv enum integer for the request's type (`uv_req_type`). +--- @param req uv.uv_req_t +--- @return string type +--- @return integer enum +function uv.req_get_type(req) end + +--- Returns the name of the struct for a given request (e.g. `"fs"` for `uv_fs_t`) +--- and the libuv enum integer for the request's type (`uv_req_type`). +--- @return string type +--- @return integer enum +function uv_req_t:get_type() end + + +--- # `uv_handle_t` - Base handle +--- +--- `uv_handle_t` is the base type for all libuv handle types. All API functions +--- defined here work with any handle type. +--- @class uv.uv_handle_t : userdata +local uv_handle_t = {} + +--- Returns `true` if the handle is active, `false` if it's inactive. What "active” +--- means depends on the type of handle: +--- +--- - A [`uv_async_t`][] handle is always active and cannot be deactivated, except +--- by closing it with `uv.close()`. +--- +--- - A [`uv_pipe_t`][], [`uv_tcp_t`][], [`uv_udp_t`][], etc. handle - basically +--- any handle that deals with I/O - is active when it is doing something that +--- involves I/O, like reading, writing, connecting, accepting new connections, +--- etc. +--- +--- - A [`uv_check_t`][], [`uv_idle_t`][], [`uv_timer_t`][], etc. handle is active +--- when it has been started with a call to `uv.check_start()`, `uv.idle_start()`, +--- `uv.timer_start()` etc. until it has been stopped with a call to its +--- respective stop function. +--- @param handle uv.uv_handle_t +--- @return boolean? active +--- @return string? err +--- @return uv.error_name? err_name +function uv.is_active(handle) end + +--- Returns `true` if the handle is active, `false` if it's inactive. What "active” +--- means depends on the type of handle: +--- +--- - A [`uv_async_t`][] handle is always active and cannot be deactivated, except +--- by closing it with `uv.close()`. +--- +--- - A [`uv_pipe_t`][], [`uv_tcp_t`][], [`uv_udp_t`][], etc. handle - basically +--- any handle that deals with I/O - is active when it is doing something that +--- involves I/O, like reading, writing, connecting, accepting new connections, +--- etc. +--- +--- - A [`uv_check_t`][], [`uv_idle_t`][], [`uv_timer_t`][], etc. handle is active +--- when it has been started with a call to `uv.check_start()`, `uv.idle_start()`, +--- `uv.timer_start()` etc. until it has been stopped with a call to its +--- respective stop function. +--- @return boolean? active +--- @return string? err +--- @return uv.error_name? err_name +function uv_handle_t:is_active() end + +--- Returns `true` if the handle is closing or closed, `false` otherwise. +--- **Note**: +--- This function should only be used between the initialization of the +--- handle and the arrival of the close callback. +--- @param handle uv.uv_handle_t +--- @return boolean? closing +--- @return string? err +--- @return uv.error_name? err_name +function uv.is_closing(handle) end + +--- Returns `true` if the handle is closing or closed, `false` otherwise. +--- **Note**: +--- This function should only be used between the initialization of the +--- handle and the arrival of the close callback. +--- @return boolean? closing +--- @return string? err +--- @return uv.error_name? err_name +function uv_handle_t:is_closing() end + +--- Request handle to be closed. `callback` will be called asynchronously after this +--- call. This MUST be called on each handle before memory is released. +--- +--- Handles that wrap file descriptors are closed immediately but `callback` will +--- still be deferred to the next iteration of the event loop. It gives you a chance +--- to free up any resources associated with the handle. +--- +--- In-progress requests, like `uv_connect_t` or `uv_write_t`, are cancelled and +--- have their callbacks called asynchronously with `ECANCELED`. +--- @param handle uv.uv_handle_t +--- @param callback fun()? +function uv.close(handle, callback) end + +--- Request handle to be closed. `callback` will be called asynchronously after this +--- call. This MUST be called on each handle before memory is released. +--- +--- Handles that wrap file descriptors are closed immediately but `callback` will +--- still be deferred to the next iteration of the event loop. It gives you a chance +--- to free up any resources associated with the handle. +--- +--- In-progress requests, like `uv_connect_t` or `uv_write_t`, are cancelled and +--- have their callbacks called asynchronously with `ECANCELED`. +--- @param callback fun()? +function uv_handle_t:close(callback) end + +--- Reference the given handle. References are idempotent, that is, if a handle is +--- already referenced calling this function again will have no effect. +--- @param handle uv.uv_handle_t +function uv.ref(handle) end + +--- Reference the given handle. References are idempotent, that is, if a handle is +--- already referenced calling this function again will have no effect. +function uv_handle_t:ref() end + +--- Un-reference the given handle. References are idempotent, that is, if a handle +--- is not referenced calling this function again will have no effect. +--- @param handle uv.uv_handle_t +function uv.unref(handle) end + +--- Un-reference the given handle. References are idempotent, that is, if a handle +--- is not referenced calling this function again will have no effect. +function uv_handle_t:unref() end + +--- Returns `true` if the handle referenced, `false` if not. +--- @param handle uv.uv_handle_t +--- @return boolean? has_ref +--- @return string? err +--- @return uv.error_name? err_name +function uv.has_ref(handle) end + +--- Returns `true` if the handle referenced, `false` if not. +--- @return boolean? has_ref +--- @return string? err +--- @return uv.error_name? err_name +function uv_handle_t:has_ref() end + +--- Gets or sets the size of the send buffer that the operating system uses for the +--- socket. +--- +--- If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. +--- +--- This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP +--- handles on Windows. +--- **Note**: +--- Linux will set double the size and return double the size of the +--- original set value. +--- @param handle uv.uv_handle_t +--- @param size integer? +--- @return integer? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.send_buffer_size(handle, size) end + +--- Gets or sets the size of the send buffer that the operating system uses for the +--- socket. +--- +--- If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. +--- +--- This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP +--- handles on Windows. +--- **Note**: +--- Linux will set double the size and return double the size of the +--- original set value. +--- @param size integer? +--- @return integer? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_handle_t:send_buffer_size(size) end + +--- Gets or sets the size of the receive buffer that the operating system uses for +--- the socket. +--- +--- If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. +--- +--- This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP +--- handles on Windows. +--- **Note**: +--- Linux will set double the size and return double the size of the +--- original set value. +--- @param handle uv.uv_handle_t +--- @param size integer? +--- @return integer? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.recv_buffer_size(handle, size) end + +--- Gets or sets the size of the receive buffer that the operating system uses for +--- the socket. +--- +--- If `size` is omitted (or `0`), this will return the current send buffer size; otherwise, this will use `size` to set the new send buffer size. +--- +--- This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP +--- handles on Windows. +--- **Note**: +--- Linux will set double the size and return double the size of the +--- original set value. +--- @param size integer? +--- @return integer? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_handle_t:recv_buffer_size(size) end + +--- Gets the platform dependent file descriptor equivalent. +--- +--- The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing any +--- other handle type will fail with `EINVAL`. +--- +--- If a handle doesn't have an attached file descriptor yet or the handle itself +--- has been closed, this function will return `EBADF`. +--- **Warning**: +--- Be very careful when using this function. libuv assumes it's in +--- control of the file descriptor so any change to it may lead to malfunction. +--- @param handle uv.uv_handle_t +--- @return integer? fileno +--- @return string? err +--- @return uv.error_name? err_name +function uv.fileno(handle) end + +--- Gets the platform dependent file descriptor equivalent. +--- +--- The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing any +--- other handle type will fail with `EINVAL`. +--- +--- If a handle doesn't have an attached file descriptor yet or the handle itself +--- has been closed, this function will return `EBADF`. +--- **Warning**: +--- Be very careful when using this function. libuv assumes it's in +--- control of the file descriptor so any change to it may lead to malfunction. +--- @return integer? fileno +--- @return string? err +--- @return uv.error_name? err_name +function uv_handle_t:fileno() end + +--- Returns the name of the struct for a given handle (e.g. `"pipe"` for `uv_pipe_t`) +--- and the libuv enum integer for the handle's type (`uv_handle_type`). +--- @param handle uv.uv_handle_t +--- @return string type +--- @return integer enum +function uv.handle_get_type(handle) end + +--- Returns the name of the struct for a given handle (e.g. `"pipe"` for `uv_pipe_t`) +--- and the libuv enum integer for the handle's type (`uv_handle_type`). +--- @return string type +--- @return integer enum +function uv_handle_t:get_type() end + + +--- # Reference counting +--- +--- The libuv event loop (if run in the default mode) will run until there are no +--- active and referenced handles left. The user can force the loop to exit early by +--- unreferencing handles which are active, for example by calling `uv.unref()` +--- after calling `uv.timer_start()`. +--- +--- A handle can be referenced or unreferenced, the refcounting scheme doesn't use a +--- counter, so both operations are idempotent. +--- +--- All handles are referenced when active by default, see `uv.is_active()` for a +--- more detailed explanation on what being active involves. + +--- # `uv_timer_t` - Timer handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Timer handles are used to schedule callbacks to be called in the future. +--- @class uv.uv_timer_t : uv.uv_handle_t +local uv_timer_t = {} + +--- Creates and initializes a new `uv_timer_t`. Returns the Lua userdata wrapping +--- it. +--- Example +--- ```lua +--- -- Creating a simple setTimeout wrapper +--- local function setTimeout(timeout, callback) +--- local timer = uv.new_timer() +--- timer:start(timeout, 0, function () +--- timer:stop() +--- timer:close() +--- callback() +--- end) +--- return timer +--- end +--- +--- -- Creating a simple setInterval wrapper +--- local function setInterval(interval, callback) +--- local timer = uv.new_timer() +--- timer:start(interval, interval, function () +--- callback() +--- end) +--- return timer +--- end +--- +--- -- And clearInterval +--- local function clearInterval(timer) +--- timer:stop() +--- timer:close() +--- end +--- ``` +--- @return uv.uv_timer_t? timer +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_timer() end + +--- Start the timer. `timeout` and `repeat` are in milliseconds. +--- +--- If `timeout` is zero, the callback fires on the next event loop iteration. If +--- `repeat` is non-zero, the callback fires first after `timeout` milliseconds and +--- then repeatedly after `repeat` milliseconds. +--- @param timer uv.uv_timer_t +--- @param timeout integer +--- @param repeat_ integer +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.timer_start(timer, timeout, repeat_, callback) end + +--- Start the timer. `timeout` and `repeat` are in milliseconds. +--- +--- If `timeout` is zero, the callback fires on the next event loop iteration. If +--- `repeat` is non-zero, the callback fires first after `timeout` milliseconds and +--- then repeatedly after `repeat` milliseconds. +--- @param timeout integer +--- @param repeat_ integer +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_timer_t:start(timeout, repeat_, callback) end + +--- Stop the timer, the callback will not be called anymore. +--- @param timer uv.uv_timer_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.timer_stop(timer) end + +--- Stop the timer, the callback will not be called anymore. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_timer_t:stop() end + +--- Stop the timer, and if it is repeating restart it using the repeat value as the +--- timeout. If the timer has never been started before it raises `EINVAL`. +--- @param timer uv.uv_timer_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.timer_again(timer) end + +--- Stop the timer, and if it is repeating restart it using the repeat value as the +--- timeout. If the timer has never been started before it raises `EINVAL`. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_timer_t:again() end + +--- Set the repeat interval value in milliseconds. The timer will be scheduled to +--- run on the given interval, regardless of the callback execution duration, and +--- will follow normal timer semantics in the case of a time-slice overrun. +--- +--- For example, if a 50 ms repeating timer first runs for 17 ms, it will be +--- scheduled to run again 33 ms later. If other tasks consume more than the 33 ms +--- following the first timer callback, then the callback will run as soon as +--- possible. +--- @param timer uv.uv_timer_t +--- @param repeat_ integer +function uv.timer_set_repeat(timer, repeat_) end + +--- Set the repeat interval value in milliseconds. The timer will be scheduled to +--- run on the given interval, regardless of the callback execution duration, and +--- will follow normal timer semantics in the case of a time-slice overrun. +--- +--- For example, if a 50 ms repeating timer first runs for 17 ms, it will be +--- scheduled to run again 33 ms later. If other tasks consume more than the 33 ms +--- following the first timer callback, then the callback will run as soon as +--- possible. +--- @param repeat_ integer +function uv_timer_t:set_repeat(repeat_) end + +--- Get the timer repeat value. +--- @param timer uv.uv_timer_t +--- @return integer repeat_ +function uv.timer_get_repeat(timer) end + +--- Get the timer repeat value. +--- @return integer repeat_ +function uv_timer_t:get_repeat() end + +--- Get the timer due value or 0 if it has expired. The time is relative to `uv.now()`. +--- @param timer uv.uv_timer_t +--- @return integer due_in +function uv.timer_get_due_in(timer) end + +--- Get the timer due value or 0 if it has expired. The time is relative to `uv.now()`. +--- @return integer due_in +function uv_timer_t:get_due_in() end + + +--- # `uv_prepare_t` - Prepare handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Prepare handles will run the given callback once per loop iteration, right +--- before polling for I/O. +--- +--- ```lua +--- local prepare = uv.new_prepare() +--- prepare:start(function() +--- print("Before I/O polling") +--- end) +--- ``` +--- @class uv.uv_prepare_t : uv.uv_handle_t +local uv_prepare_t = {} + +--- Creates and initializes a new `uv_prepare_t`. Returns the Lua userdata wrapping +--- it. +--- @return uv.uv_prepare_t +function uv.new_prepare() end + +--- Start the handle with the given callback. +--- @param prepare uv.uv_prepare_t +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.prepare_start(prepare, callback) end + +--- Start the handle with the given callback. +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_prepare_t:start(callback) end + +--- Stop the handle, the callback will no longer be called. +--- @param prepare uv.uv_prepare_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.prepare_stop(prepare) end + +--- Stop the handle, the callback will no longer be called. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_prepare_t:stop() end + + +--- # `uv_check_t` - Check handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Check handles will run the given callback once per loop iteration, right after +--- polling for I/O. +--- +--- ```lua +--- local check = uv.new_check() +--- check:start(function() +--- print("After I/O polling") +--- end) +--- ``` +--- @class uv.uv_check_t : uv.uv_handle_t +local uv_check_t = {} + +--- Creates and initializes a new `uv_check_t`. Returns the Lua userdata wrapping +--- it. +--- @return uv.uv_check_t +function uv.new_check() end + +--- Start the handle with the given callback. +--- @param check uv.uv_check_t +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.check_start(check, callback) end + +--- Start the handle with the given callback. +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_check_t:start(callback) end + +--- Stop the handle, the callback will no longer be called. +--- @param check uv.uv_check_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.check_stop(check) end + +--- Stop the handle, the callback will no longer be called. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_check_t:stop() end + + +--- # `uv_idle_t` - Idle handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Idle handles will run the given callback once per loop iteration, right before +--- the [`uv_prepare_t`][] handles. +--- +--- **Note**: The notable difference with prepare handles is that when there are +--- active idle handles, the loop will perform a zero timeout poll instead of +--- blocking for I/O. +--- +--- **Warning**: Despite the name, idle handles will get their callbacks called on +--- every loop iteration, not when the loop is actually "idle". +--- +--- ```lua +--- local idle = uv.new_idle() +--- idle:start(function() +--- print("Before I/O polling, no blocking") +--- end) +--- ``` +--- @class uv.uv_idle_t : uv.uv_handle_t +local uv_idle_t = {} + +--- Creates and initializes a new `uv_idle_t`. Returns the Lua userdata wrapping +--- it. +--- @return uv.uv_idle_t +function uv.new_idle() end + +--- Start the handle with the given callback. +--- @param idle uv.uv_idle_t +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.idle_start(idle, callback) end + +--- Start the handle with the given callback. +--- @param callback fun() +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_idle_t:start(callback) end + +--- Stop the handle, the callback will no longer be called. +--- @param idle uv.uv_idle_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.idle_stop(idle) end + +--- Stop the handle, the callback will no longer be called. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_idle_t:stop() end + + +--- # `uv_async_t` - Async handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Async handles allow the user to "wakeup" the event loop and get a callback +--- called from another thread. +--- +--- ```lua +--- local async +--- async = uv.new_async(function() +--- print("async operation ran") +--- async:close() +--- end) +--- +--- async:send() +--- ``` +--- @class uv.uv_async_t : uv.uv_handle_t +local uv_async_t = {} + +--- Creates and initializes a new `uv_async_t`. Returns the Lua userdata wrapping +--- it. +--- **Note**: +--- Unlike other handle initialization functions, this immediately starts +--- the handle. +--- @param callback fun(...: uv.threadargs) +--- @return uv.uv_async_t? async +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_async(callback) end + +--- Wakeup the event loop and call the async handle's callback. +--- **Note**: +--- It's safe to call this function from any thread. The callback will be +--- called on the loop thread. +--- **Warning**: +--- libuv will coalesce calls to `uv.async_send(async)`, that is, not +--- every call to it will yield an execution of the callback. For example: if +--- `uv.async_send()` is called 5 times in a row before the callback is called, the +--- callback will only be called once. If `uv.async_send()` is called again after +--- the callback was called, it will be called again. +--- @param async uv.uv_async_t +--- @param ... uv.threadargs +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.async_send(async, ...) end + +--- Wakeup the event loop and call the async handle's callback. +--- **Note**: +--- It's safe to call this function from any thread. The callback will be +--- called on the loop thread. +--- **Warning**: +--- libuv will coalesce calls to `uv.async_send(async)`, that is, not +--- every call to it will yield an execution of the callback. For example: if +--- `uv.async_send()` is called 5 times in a row before the callback is called, the +--- callback will only be called once. If `uv.async_send()` is called again after +--- the callback was called, it will be called again. +--- @param ... uv.threadargs +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_async_t:send(...) end + + +--- # `uv_poll_t` - Poll handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Poll handles are used to watch file descriptors for readability and writability, +--- similar to the purpose of [poll(2)](http://linux.die.net/man/2/poll). +--- +--- The purpose of poll handles is to enable integrating external libraries that +--- rely on the event loop to signal it about the socket status changes, like c-ares +--- or libssh2. Using `uv_poll_t` for any other purpose is not recommended; +--- `uv_tcp_t`, `uv_udp_t`, etc. provide an implementation that is faster and more +--- scalable than what can be achieved with `uv_poll_t`, especially on Windows. +--- +--- It is possible that poll handles occasionally signal that a file descriptor is +--- readable or writable even when it isn't. The user should therefore always be +--- prepared to handle EAGAIN or equivalent when it attempts to read from or write +--- to the fd. +--- +--- It is not okay to have multiple active poll handles for the same socket, this +--- can cause libuv to busyloop or otherwise malfunction. +--- +--- The user should not close a file descriptor while it is being polled by an +--- active poll handle. This can cause the handle to report an error, but it might +--- also start polling another socket. However the fd can be safely closed +--- immediately after a call to `uv.poll_stop()` or `uv.close()`. +--- +--- **Note**: On windows only sockets can be polled with poll handles. On Unix any +--- file descriptor that would be accepted by poll(2) can be used. +--- @class uv.uv_poll_t : uv.uv_handle_t +local uv_poll_t = {} + +--- Initialize the handle using a file descriptor. +--- +--- The file descriptor is set to non-blocking mode. +--- @param fd integer +--- @return uv.uv_poll_t? poll +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_poll(fd) end + +--- Initialize the handle using a socket descriptor. On Unix this is identical to +--- `uv.new_poll()`. On windows it takes a SOCKET handle. +--- +--- The socket is set to non-blocking mode. +--- @param fd integer +--- @return uv.uv_poll_t? poll +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_socket_poll(fd) end + +--- Starts polling the file descriptor. `events` are: `"r"`, `"w"`, `"rw"`, `"d"`, +--- `"rd"`, `"wd"`, `"rwd"`, `"p"`, `"rp"`, `"wp"`, `"rwp"`, `"dp"`, `"rdp"`, +--- `"wdp"`, or `"rwdp"` where `r` is `READABLE`, `w` is `WRITABLE`, `d` is +--- `DISCONNECT`, and `p` is `PRIORITIZED`. As soon as an event is detected +--- the callback will be called with status set to 0, and the detected events set on +--- the events field. +--- +--- The user should not close the socket while the handle is active. If the user +--- does that anyway, the callback may be called reporting an error status, but this +--- is not guaranteed. +--- **Note**: +--- Calling `uv.poll_start()` on a handle that is already active is fine. +--- Doing so will update the events mask that is being watched for. +--- @param poll uv.uv_poll_t +--- @param events string? +--- @param callback fun(err: string?, events: string?) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.poll_start(poll, events, callback) end + +--- Starts polling the file descriptor. `events` are: `"r"`, `"w"`, `"rw"`, `"d"`, +--- `"rd"`, `"wd"`, `"rwd"`, `"p"`, `"rp"`, `"wp"`, `"rwp"`, `"dp"`, `"rdp"`, +--- `"wdp"`, or `"rwdp"` where `r` is `READABLE`, `w` is `WRITABLE`, `d` is +--- `DISCONNECT`, and `p` is `PRIORITIZED`. As soon as an event is detected +--- the callback will be called with status set to 0, and the detected events set on +--- the events field. +--- +--- The user should not close the socket while the handle is active. If the user +--- does that anyway, the callback may be called reporting an error status, but this +--- is not guaranteed. +--- **Note**: +--- Calling `uv.poll_start()` on a handle that is already active is fine. +--- Doing so will update the events mask that is being watched for. +--- @param events string? +--- @param callback fun(err: string?, events: string?) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_poll_t:start(events, callback) end + +--- Stop polling the file descriptor, the callback will no longer be called. +--- @param poll uv.uv_poll_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.poll_stop(poll) end + +--- Stop polling the file descriptor, the callback will no longer be called. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_poll_t:stop() end + + +--- # `uv_signal_t` - Signal handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Signal handles implement Unix style signal handling on a per-event loop bases. +--- +--- **Windows Notes:** +--- +--- Reception of some signals is emulated on Windows: +--- - SIGINT is normally delivered when the user presses CTRL+C. However, like on +--- Unix, it is not generated when terminal raw mode is enabled. +--- - SIGBREAK is delivered when the user pressed CTRL + BREAK. +--- - SIGHUP is generated when the user closes the console window. On SIGHUP the +--- program is given approximately 10 seconds to perform cleanup. After that +--- Windows will unconditionally terminate it. +--- - SIGWINCH is raised whenever libuv detects that the console has been resized. +--- SIGWINCH is emulated by libuv when the program uses a uv_tty_t handle to write +--- to the console. SIGWINCH may not always be delivered in a timely manner; libuv +--- will only detect size changes when the cursor is being moved. When a readable +--- [`uv_tty_t`][] handle is used in raw mode, resizing the console buffer will +--- also trigger a SIGWINCH signal. +--- - Watchers for other signals can be successfully created, but these signals +--- are never received. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV, +--- SIGTERM and SIGKILL. +--- - Calls to raise() or abort() to programmatically raise a signal are not +--- detected by libuv; these will not trigger a signal watcher. +--- +--- **Unix Notes:** +--- +--- - SIGKILL and SIGSTOP are impossible to catch. +--- - Handling SIGBUS, SIGFPE, SIGILL or SIGSEGV via libuv results into undefined +--- behavior. +--- - SIGABRT will not be caught by libuv if generated by abort(), e.g. through +--- assert(). +--- - On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL pthreads +--- library to manage threads. Installing watchers for those signals will lead to +--- unpredictable behavior and is strongly discouraged. Future versions of libuv +--- may simply reject them. +--- +--- ```lua +--- -- Create a new signal handler +--- local signal = uv.new_signal() +--- -- Define a handler function +--- uv.signal_start(signal, "sigint", function(signame) +--- print("got " .. signame .. ", shutting down") +--- os.exit(1) +--- end) +--- ``` +--- @class uv.uv_signal_t : uv.uv_handle_t +local uv_signal_t = {} + +--- Creates and initializes a new `uv_signal_t`. Returns the Lua userdata wrapping +--- it. +--- @return uv.uv_signal_t? signal +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_signal() end + +--- Start the handle with the given callback, watching for the given signal. +--- +--- See [Constants][] for supported `signame` input and output values. +--- @param signal uv.uv_signal_t +--- @param signame string|integer +--- @param callback fun(signame: string) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.signal_start(signal, signame, callback) end + +--- Start the handle with the given callback, watching for the given signal. +--- +--- See [Constants][] for supported `signame` input and output values. +--- @param signame string|integer +--- @param callback fun(signame: string) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_signal_t:start(signame, callback) end + +--- Same functionality as `uv.signal_start()` but the signal handler is reset the moment the signal is received. +--- +--- See [Constants][] for supported `signame` input and output values. +--- @param signal uv.uv_signal_t +--- @param signame string|integer +--- @param callback fun(signame: string) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.signal_start_oneshot(signal, signame, callback) end + +--- Same functionality as `uv.signal_start()` but the signal handler is reset the moment the signal is received. +--- +--- See [Constants][] for supported `signame` input and output values. +--- @param signame string|integer +--- @param callback fun(signame: string) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_signal_t:start_oneshot(signame, callback) end + +--- Stop the handle, the callback will no longer be called. +--- @param signal uv.uv_signal_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.signal_stop(signal) end + +--- Stop the handle, the callback will no longer be called. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_signal_t:stop() end + + +--- # `uv_process_t` - Process handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Process handles will spawn a new process and allow the user to control it and +--- establish communication channels with it using streams. +--- @class uv.uv_process_t : uv.uv_handle_t +local uv_process_t = {} + +--- Disables inheritance for file descriptors / handles that this process inherited +--- from its parent. The effect is that child processes spawned by this process +--- don't accidentally inherit these handles. +--- +--- It is recommended to call this function as early in your program as possible, +--- before the inherited file descriptors can be closed or duplicated. +--- **Note**: +--- This function works on a best-effort basis: there is no guarantee that +--- libuv can discover all file descriptors that were inherited. In general it does +--- a better job on Windows than it does on Unix. +function uv.disable_stdio_inheritance() end + +--- @class uv.spawn.options +--- +--- Command line arguments as a list of strings. The first +--- string should *not* be the path to the program, since that is already +--- provided via `path`. On Windows, this uses CreateProcess which concatenates +--- the arguments into a string. This can cause some strange errors +--- (see `options.verbatim` below for Windows). +--- @field args string[]? +--- +--- Set the file descriptors that will be made available to +--- the child process. The convention is that the first entries are stdin, stdout, +--- and stderr. +--- +--- The entries can take many shapes. +--- - If `integer`, then the child process inherits that same zero-indexed +--- fd from the parent process. +--- - If `uv_stream_t` handles are passed in, those are used as a read-write pipe +--- or inherited stream depending if the stream has a valid fd. +--- - If `nil`, means to ignore that fd in the child process. +--- +--- **Note**: On Windows, file descriptors after the third are +--- available to the child process only if the child processes uses the MSVCRT +--- runtime. +--- @field stdio table? +--- +--- Set environment variables for the new process. +--- @field env table? +--- +--- Set the current working directory for the sub-process. +--- @field cwd string? +--- +--- Set the child process' user id. +--- @field uid string? +--- +--- Set the child process' group id. +--- @field gid string? +--- +--- If true, do not wrap any arguments in quotes, or +--- perform any other escaping, when converting the argument list into a command +--- line string. This option is only meaningful on Windows systems. On Unix it is +--- silently ignored. +--- @field verbatim boolean? +--- +--- If true, spawn the child process in a detached state - +--- this will make it a process group leader, and will effectively enable the +--- child to keep running after the parent exits. Note that the child process +--- will still keep the parent's event loop alive unless the parent process calls +--- `uv.unref()` on the child's process handle. +--- @field detached boolean? +--- +--- If true, hide the subprocess console window that would +--- normally be created. This option is only meaningful on Windows systems. On +--- Unix it is silently ignored. +--- @field hide boolean? + +--- Initializes the process handle and starts the process. If the process is +--- successfully spawned, this function will return the handle and pid of the child +--- process. +--- +--- Possible reasons for failing to spawn would include (but not be limited to) the +--- file to execute not existing, not having permissions to use the setuid or setgid +--- specified, or not having enough memory to allocate for the new process. +--- +--- ```lua +--- local stdin = uv.new_pipe() +--- local stdout = uv.new_pipe() +--- local stderr = uv.new_pipe() +--- +--- print("stdin", stdin) +--- print("stdout", stdout) +--- print("stderr", stderr) +--- +--- local handle, pid = uv.spawn("cat", { +--- stdio = {stdin, stdout, stderr} +--- }, function(code, signal) -- on exit +--- print("exit code", code) +--- print("exit signal", signal) +--- end) +--- +--- print("process opened", handle, pid) +--- +--- uv.read_start(stdout, function(err, data) +--- assert(not err, err) +--- if data then +--- print("stdout chunk", stdout, data) +--- else +--- print("stdout end", stdout) +--- end +--- end) +--- +--- uv.read_start(stderr, function(err, data) +--- assert(not err, err) +--- if data then +--- print("stderr chunk", stderr, data) +--- else +--- print("stderr end", stderr) +--- end +--- end) +--- +--- uv.write(stdin, "Hello World") +--- +--- uv.shutdown(stdin, function() +--- print("stdin shutdown", stdin) +--- uv.close(handle, function() +--- print("process closed", handle, pid) +--- end) +--- end) +--- ``` +--- +--- When the child process exits, `on_exit` is called with an exit code and signal. +--- @param path string +--- @param options uv.spawn.options +--- @param on_exit fun(code: integer, signal: integer) +--- @return uv.uv_process_t handle +--- @return integer pid +function uv.spawn(path, options, on_exit) end + +--- Sends the specified signal to the given process handle. Check the documentation +--- on `uv_signal_t` for signal support, specially on Windows. +--- +--- See [Constants][] for supported `signame` input values. +--- @param process uv.uv_process_t +--- @param signame string|integer? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.process_kill(process, signame) end + +--- Sends the specified signal to the given process handle. Check the documentation +--- on `uv_signal_t` for signal support, specially on Windows. +--- +--- See [Constants][] for supported `signame` input values. +--- @param signame string|integer? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_process_t:kill(signame) end + +--- Sends the specified signal to the given PID. Check the documentation on +--- `uv_signal_t` for signal support, specially on Windows. +--- +--- See [Constants][] for supported `signame` input values. +--- @param pid integer +--- @param signame string|integer? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.kill(pid, signame) end + +--- Returns the handle's pid. +--- @param process uv.uv_process_t +--- @return integer +function uv.process_get_pid(process) end + +--- Returns the handle's pid. +--- @return integer +function uv_process_t:get_pid() end + + +--- # `uv_stream_t` - Stream handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- Stream handles provide an abstraction of a duplex communication channel. +--- [`uv_stream_t`][] is an abstract type, libuv provides 3 stream implementations +--- in the form of [`uv_tcp_t`][], [`uv_pipe_t`][] and [`uv_tty_t`][]. +--- @class uv.uv_stream_t : uv.uv_handle_t +local uv_stream_t = {} + +--- Shutdown the outgoing (write) side of a duplex stream. It waits for pending +--- write requests to complete. The callback is called after shutdown is complete. +--- @param stream uv.uv_stream_t +--- @param callback fun(err: string?)? +--- @return uv.uv_shutdown_t? shutdown +--- @return string? err +--- @return uv.error_name? err_name +function uv.shutdown(stream, callback) end + +--- Shutdown the outgoing (write) side of a duplex stream. It waits for pending +--- write requests to complete. The callback is called after shutdown is complete. +--- @param callback fun(err: string?)? +--- @return uv.uv_shutdown_t? shutdown +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:shutdown(callback) end + +--- Start listening for incoming connections. `backlog` indicates the number of +--- connections the kernel might queue, same as `listen(2)`. When a new incoming +--- connection is received the callback is called. +--- @param stream uv.uv_stream_t +--- @param backlog integer +--- @param callback fun(err: string?) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.listen(stream, backlog, callback) end + +--- Start listening for incoming connections. `backlog` indicates the number of +--- connections the kernel might queue, same as `listen(2)`. When a new incoming +--- connection is received the callback is called. +--- @param backlog integer +--- @param callback fun(err: string?) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:listen(backlog, callback) end + +--- This call is used in conjunction with `uv.listen()` to accept incoming +--- connections. Call this function after receiving a callback to accept the +--- connection. +--- +--- When the connection callback is called it is guaranteed that this function +--- will complete successfully the first time. If you attempt to use it more than +--- once, it may fail. It is suggested to only call this function once per +--- connection call. +--- Example +--- ```lua +--- server:listen(128, function (err) +--- local client = uv.new_tcp() +--- server:accept(client) +--- end) +--- ``` +--- @param stream uv.uv_stream_t +--- @param client_stream uv.uv_stream_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.accept(stream, client_stream) end + +--- This call is used in conjunction with `uv.listen()` to accept incoming +--- connections. Call this function after receiving a callback to accept the +--- connection. +--- +--- When the connection callback is called it is guaranteed that this function +--- will complete successfully the first time. If you attempt to use it more than +--- once, it may fail. It is suggested to only call this function once per +--- connection call. +--- Example +--- ```lua +--- server:listen(128, function (err) +--- local client = uv.new_tcp() +--- server:accept(client) +--- end) +--- ``` +--- @param client_stream uv.uv_stream_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:accept(client_stream) end + +--- Read data from an incoming stream. The callback will be made several times until +--- there is no more data to read or `uv.read_stop()` is called. When we've reached +--- EOF, `data` will be `nil`. +--- Example +--- ```lua +--- stream:read_start(function (err, chunk) +--- if err then +--- -- handle read error +--- elseif chunk then +--- -- handle data +--- else +--- -- handle disconnect +--- end +--- end) +--- ``` +--- @param stream uv.uv_stream_t +--- @param callback fun(err: string?, data: string?) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.read_start(stream, callback) end + +--- Read data from an incoming stream. The callback will be made several times until +--- there is no more data to read or `uv.read_stop()` is called. When we've reached +--- EOF, `data` will be `nil`. +--- Example +--- ```lua +--- stream:read_start(function (err, chunk) +--- if err then +--- -- handle read error +--- elseif chunk then +--- -- handle data +--- else +--- -- handle disconnect +--- end +--- end) +--- ``` +--- @param callback fun(err: string?, data: string?) +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:read_start(callback) end + +--- Stop reading data from the stream. The read callback will no longer be called. +--- +--- This function is idempotent and may be safely called on a stopped stream. +--- @param stream uv.uv_stream_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.read_stop(stream) end + +--- Stop reading data from the stream. The read callback will no longer be called. +--- +--- This function is idempotent and may be safely called on a stopped stream. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:read_stop() end + +--- Write data to stream. +--- +--- `data` can either be a Lua string or a table of strings. If a table is passed +--- in, the C backend will use writev to send all strings in a single system call. +--- +--- The optional `callback` is for knowing when the write is complete. +--- @param stream uv.uv_stream_t +--- @param data uv.buffer +--- @param callback fun(err: string?)? +--- @return uv.uv_write_t? write +--- @return string? err +--- @return uv.error_name? err_name +function uv.write(stream, data, callback) end + +--- Write data to stream. +--- +--- `data` can either be a Lua string or a table of strings. If a table is passed +--- in, the C backend will use writev to send all strings in a single system call. +--- +--- The optional `callback` is for knowing when the write is complete. +--- @param data uv.buffer +--- @param callback fun(err: string?)? +--- @return uv.uv_write_t? write +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:write(data, callback) end + +--- Extended write function for sending handles over a pipe. The pipe must be +--- initialized with `ipc` option `true`. +--- **Note**: +--- `send_handle` must be a TCP socket or pipe, which is a server or a +--- connection (listening or connected state). Bound sockets or pipes will be +--- assumed to be servers. +--- @param stream uv.uv_stream_t +--- @param data uv.buffer +--- @param send_handle uv.uv_stream_t +--- @param callback fun(err: string?)? +--- @return uv.uv_write_t? write +--- @return string? err +--- @return uv.error_name? err_name +function uv.write2(stream, data, send_handle, callback) end + +--- Extended write function for sending handles over a pipe. The pipe must be +--- initialized with `ipc` option `true`. +--- **Note**: +--- `send_handle` must be a TCP socket or pipe, which is a server or a +--- connection (listening or connected state). Bound sockets or pipes will be +--- assumed to be servers. +--- @param data uv.buffer +--- @param send_handle uv.uv_stream_t +--- @param callback fun(err: string?)? +--- @return uv.uv_write_t? write +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:write2(data, send_handle, callback) end + +--- Same as `uv.write()`, but won't queue a write request if it can't be completed +--- immediately. +--- +--- Will return number of bytes written (can be less than the supplied buffer size). +--- @param stream uv.uv_stream_t +--- @param data uv.buffer +--- @return integer? bytes_written +--- @return string? err +--- @return uv.error_name? err_name +function uv.try_write(stream, data) end + +--- Same as `uv.write()`, but won't queue a write request if it can't be completed +--- immediately. +--- +--- Will return number of bytes written (can be less than the supplied buffer size). +--- @param data uv.buffer +--- @return integer? bytes_written +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:try_write(data) end + +--- Like `uv.write2()`, but with the properties of `uv.try_write()`. Not supported on Windows, where it returns `UV_EAGAIN`. +--- +--- Will return number of bytes written (can be less than the supplied buffer size). +--- @param stream uv.uv_stream_t +--- @param data uv.buffer +--- @param send_handle uv.uv_stream_t +--- @return integer? bytes_written +--- @return string? err +--- @return uv.error_name? err_name +function uv.try_write2(stream, data, send_handle) end + +--- Like `uv.write2()`, but with the properties of `uv.try_write()`. Not supported on Windows, where it returns `UV_EAGAIN`. +--- +--- Will return number of bytes written (can be less than the supplied buffer size). +--- @param data uv.buffer +--- @param send_handle uv.uv_stream_t +--- @return integer? bytes_written +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:try_write2(data, send_handle) end + +--- Returns `true` if the stream is readable, `false` otherwise. +--- @param stream uv.uv_stream_t +--- @return boolean +function uv.is_readable(stream) end + +--- Returns `true` if the stream is readable, `false` otherwise. +--- @return boolean +function uv_stream_t:is_readable() end + +--- Returns `true` if the stream is writable, `false` otherwise. +--- @param stream uv.uv_stream_t +--- @return boolean +function uv.is_writable(stream) end + +--- Returns `true` if the stream is writable, `false` otherwise. +--- @return boolean +function uv_stream_t:is_writable() end + +--- Enable or disable blocking mode for a stream. +--- +--- When blocking mode is enabled all writes complete synchronously. The interface +--- remains unchanged otherwise, e.g. completion or failure of the operation will +--- still be reported through a callback which is made asynchronously. +--- **Warning**: +--- Relying too much on this API is not recommended. It is likely to +--- change significantly in the future. Currently this only works on Windows and +--- only for `uv_pipe_t` handles. Also libuv currently makes no ordering guarantee +--- when the blocking mode is changed after write requests have already been +--- submitted. Therefore it is recommended to set the blocking mode immediately +--- after opening or creating the stream. +--- @param stream uv.uv_stream_t +--- @param blocking boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.stream_set_blocking(stream, blocking) end + +--- Enable or disable blocking mode for a stream. +--- +--- When blocking mode is enabled all writes complete synchronously. The interface +--- remains unchanged otherwise, e.g. completion or failure of the operation will +--- still be reported through a callback which is made asynchronously. +--- **Warning**: +--- Relying too much on this API is not recommended. It is likely to +--- change significantly in the future. Currently this only works on Windows and +--- only for `uv_pipe_t` handles. Also libuv currently makes no ordering guarantee +--- when the blocking mode is changed after write requests have already been +--- submitted. Therefore it is recommended to set the blocking mode immediately +--- after opening or creating the stream. +--- @param blocking boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_stream_t:set_blocking(blocking) end + +--- Returns the stream's write queue size. +--- @param stream uv.uv_stream_t +--- @return integer +function uv.stream_get_write_queue_size(stream) end + +--- Returns the stream's write queue size. +--- @return integer +function uv_stream_t:get_write_queue_size() end + + +--- # `uv_tcp_t` - TCP handle +--- +--- > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. +--- +--- TCP handles are used to represent both TCP streams and servers. +--- @class uv.uv_tcp_t : uv.uv_stream_t +local uv_tcp_t = {} + +--- Creates and initializes a new `uv_tcp_t`. Returns the Lua userdata wrapping it. +--- +--- If set, `flags` must be a valid address family. See [Constants][] for supported +--- address family input values. +--- @param flags string|integer? +--- @return uv.uv_tcp_t? tcp +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_tcp(flags) end + +--- Open an existing file descriptor or SOCKET as a TCP handle. +--- **Note**: +--- The passed file descriptor or SOCKET is not checked for its type, but it's required that it represents a valid stream socket. +--- @param tcp uv.uv_tcp_t +--- @param sock integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_open(tcp, sock) end + +--- Open an existing file descriptor or SOCKET as a TCP handle. +--- **Note**: +--- The passed file descriptor or SOCKET is not checked for its type, but it's required that it represents a valid stream socket. +--- @param sock integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:open(sock) end + +--- Enable / disable Nagle's algorithm. +--- @param tcp uv.uv_tcp_t +--- @param enable boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_nodelay(tcp, enable) end + +--- Enable / disable Nagle's algorithm. +--- @param enable boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:nodelay(enable) end + +--- Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, +--- ignored when enable is `false`. +--- @param tcp uv.uv_tcp_t +--- @param enable boolean +--- @param delay integer? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_keepalive(tcp, enable, delay) end + +--- Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, +--- ignored when enable is `false`. +--- @param enable boolean +--- @param delay integer? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:keepalive(enable, delay) end + +--- Enable / disable simultaneous asynchronous accept requests that are queued by +--- the operating system when listening for new TCP connections. +--- +--- This setting is used to tune a TCP server for the desired performance. Having +--- simultaneous accepts can significantly improve the rate of accepting connections +--- (which is why it is enabled by default) but may lead to uneven load distribution +--- in multi-process setups. +--- @param tcp uv.uv_tcp_t +--- @param enable boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_simultaneous_accepts(tcp, enable) end + +--- Enable / disable simultaneous asynchronous accept requests that are queued by +--- the operating system when listening for new TCP connections. +--- +--- This setting is used to tune a TCP server for the desired performance. Having +--- simultaneous accepts can significantly improve the rate of accepting connections +--- (which is why it is enabled by default) but may lead to uneven load distribution +--- in multi-process setups. +--- @param enable boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:simultaneous_accepts(enable) end + +--- Bind the handle to an host and port. `host` should be an IP address and +--- not a domain name. Any `flags` are set with a table with field `ipv6only` +--- equal to `true` or `false`. +--- +--- When the port is already taken, you can expect to see an `EADDRINUSE` error +--- from either `uv.tcp_bind()`, `uv.listen()` or `uv.tcp_connect()`. That is, a +--- successful call to this function does not guarantee that the call to `uv.listen()` +--- or `uv.tcp_connect()` will succeed as well. +--- +--- Use a port of `0` to let the OS assign an ephemeral port. You can look it up +--- later using `uv.tcp_getsockname()`. +--- @param tcp uv.uv_tcp_t +--- @param host string +--- @param port integer +--- @param flags { ipv6only: boolean }? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_bind(tcp, host, port, flags) end + +--- Bind the handle to an host and port. `host` should be an IP address and +--- not a domain name. Any `flags` are set with a table with field `ipv6only` +--- equal to `true` or `false`. +--- +--- When the port is already taken, you can expect to see an `EADDRINUSE` error +--- from either `uv.tcp_bind()`, `uv.listen()` or `uv.tcp_connect()`. That is, a +--- successful call to this function does not guarantee that the call to `uv.listen()` +--- or `uv.tcp_connect()` will succeed as well. +--- +--- Use a port of `0` to let the OS assign an ephemeral port. You can look it up +--- later using `uv.tcp_getsockname()`. +--- @param host string +--- @param port integer +--- @param flags { ipv6only: boolean }? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:bind(host, port, flags) end + +--- Get the address of the peer connected to the handle. +--- +--- See [Constants][] for supported address `family` output values. +--- @param tcp uv.uv_tcp_t +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_getpeername(tcp) end + +--- Get the address of the peer connected to the handle. +--- +--- See [Constants][] for supported address `family` output values. +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:getpeername() end + +--- Get the current address to which the handle is bound. +--- +--- See [Constants][] for supported address `family` output values. +--- @param tcp uv.uv_tcp_t +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_getsockname(tcp) end + +--- Get the current address to which the handle is bound. +--- +--- See [Constants][] for supported address `family` output values. +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:getsockname() end + +--- Establish an IPv4 or IPv6 TCP connection. +--- Example +--- ```lua +--- local client = uv.new_tcp() +--- client:connect("127.0.0.1", 8080, function (err) +--- -- check error and carry on. +--- end) +--- ``` +--- @param tcp uv.uv_tcp_t +--- @param host string +--- @param port integer +--- @param callback fun(err: string?) +--- @return uv.uv_connect_t? connect +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_connect(tcp, host, port, callback) end + +--- Establish an IPv4 or IPv6 TCP connection. +--- Example +--- ```lua +--- local client = uv.new_tcp() +--- client:connect("127.0.0.1", 8080, function (err) +--- -- check error and carry on. +--- end) +--- ``` +--- @param host string +--- @param port integer +--- @param callback fun(err: string?) +--- @return uv.uv_connect_t? connect +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:connect(host, port, callback) end + +--- @deprecated Please use `uv.stream_get_write_queue_size()` instead. +--- @param tcp uv.uv_tcp_t +function uv.tcp_write_queue_size(tcp) end + +--- @deprecated Please use `uv.stream_get_write_queue_size()` instead. +function uv_tcp_t:write_queue_size() end + +--- Resets a TCP connection by sending a RST packet. This is accomplished by setting +--- the SO_LINGER socket option with a linger interval of zero and then calling +--- `uv.close()`. Due to some platform inconsistencies, mixing of `uv.shutdown()` +--- and `uv.tcp_close_reset()` calls is not allowed. +--- @param tcp uv.uv_tcp_t +--- @param callback fun()? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tcp_close_reset(tcp, callback) end + +--- Resets a TCP connection by sending a RST packet. This is accomplished by setting +--- the SO_LINGER socket option with a linger interval of zero and then calling +--- `uv.close()`. Due to some platform inconsistencies, mixing of `uv.shutdown()` +--- and `uv.tcp_close_reset()` calls is not allowed. +--- @param callback fun()? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_tcp_t:close_reset(callback) end + +--- Create a pair of connected sockets with the specified properties. The resulting handles can be passed to `uv.tcp_open`, used with `uv.spawn`, or for any other purpose. +--- +--- See [Constants][] for supported `socktype` input values. +--- +--- When `protocol` is set to 0 or nil, it will be automatically chosen based on the socket's domain and type. When `protocol` is specified as a string, it will be looked up using the `getprotobyname(3)` function (examples: `"ip"`, `"icmp"`, `"tcp"`, `"udp"`, etc). +--- +--- Flags: +--- - `nonblock`: Opens the specified socket handle for `OVERLAPPED` or `FIONBIO`/`O_NONBLOCK` I/O usage. This is recommended for handles that will be used by libuv, and not usually recommended otherwise. +--- +--- Equivalent to `socketpair(2)` with a domain of `AF_UNIX`. +--- Example +--- ```lua +--- -- Simple read/write with tcp +--- local fds = uv.socketpair(nil, nil, {nonblock=true}, {nonblock=true}) +--- +--- local sock1 = uv.new_tcp() +--- sock1:open(fds[1]) +--- +--- local sock2 = uv.new_tcp() +--- sock2:open(fds[2]) +--- +--- sock1:write("hello") +--- sock2:read_start(function(err, chunk) +--- assert(not err, err) +--- print(chunk) +--- end) +--- ``` +--- @param socktype string|integer? +--- @param protocol string|integer? +--- @param flags1 { nonblock: boolean }? +--- @param flags2 { nonblock: boolean }? +--- @return [integer, integer]? fds +--- @return string? err +--- @return uv.error_name? err_name +function uv.socketpair(socktype, protocol, flags1, flags2) end + + +--- # `uv_pipe_t` - Pipe handle +--- +--- > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. +--- +--- Pipe handles provide an abstraction over local domain sockets on Unix and named pipes on Windows. +--- +--- ```lua +--- local pipe = uv.new_pipe(false) +--- +--- pipe:bind('/tmp/sock.test') +--- +--- pipe:listen(128, function() +--- local client = uv.new_pipe(false) +--- pipe:accept(client) +--- client:write("hello!\n") +--- client:close() +--- end) +--- ``` +--- @class uv.uv_pipe_t : uv.uv_stream_t +local uv_pipe_t = {} + +--- Creates and initializes a new `uv_pipe_t`. Returns the Lua userdata wrapping +--- it. The `ipc` argument is a boolean to indicate if this pipe will be used for +--- handle passing between processes. +--- @param ipc boolean? +--- @return uv.uv_pipe_t? pipe +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_pipe(ipc) end + +--- Open an existing file descriptor or [`uv_handle_t`][] as a pipe. +--- **Note**: +--- The file descriptor is set to non-blocking mode. +--- @param pipe uv.uv_pipe_t +--- @param fd integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_open(pipe, fd) end + +--- Open an existing file descriptor or [`uv_handle_t`][] as a pipe. +--- **Note**: +--- The file descriptor is set to non-blocking mode. +--- @param fd integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:open(fd) end + +--- Bind the pipe to a file path (Unix) or a name (Windows). +--- **Note**: +--- Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- @param pipe uv.uv_pipe_t +--- @param name string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_bind(pipe, name) end + +--- Bind the pipe to a file path (Unix) or a name (Windows). +--- **Note**: +--- Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- @param name string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:bind(name) end + +--- Connect to the Unix domain socket or the named pipe. +--- **Note**: +--- Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- @param pipe uv.uv_pipe_t +--- @param name string +--- @param callback fun(err: string?)? +--- @return uv.uv_connect_t? connect +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_connect(pipe, name, callback) end + +--- Connect to the Unix domain socket or the named pipe. +--- **Note**: +--- Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- @param name string +--- @param callback fun(err: string?)? +--- @return uv.uv_connect_t? connect +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:connect(name, callback) end + +--- Get the name of the Unix domain socket or the named pipe. +--- @param pipe uv.uv_pipe_t +--- @return string? name +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_getsockname(pipe) end + +--- Get the name of the Unix domain socket or the named pipe. +--- @return string? name +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:getsockname() end + +--- Get the name of the Unix domain socket or the named pipe to which the handle is +--- connected. +--- @param pipe uv.uv_pipe_t +--- @return string? name +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_getpeername(pipe) end + +--- Get the name of the Unix domain socket or the named pipe to which the handle is +--- connected. +--- @return string? name +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:getpeername() end + +--- Set the number of pending pipe instance handles when the pipe server is waiting +--- for connections. +--- **Note**: +--- This setting applies to Windows only. +--- @param pipe uv.uv_pipe_t +--- @param count integer +function uv.pipe_pending_instances(pipe, count) end + +--- Set the number of pending pipe instance handles when the pipe server is waiting +--- for connections. +--- **Note**: +--- This setting applies to Windows only. +--- @param count integer +function uv_pipe_t:pending_instances(count) end + +--- Returns the pending pipe count for the named pipe. +--- @param pipe uv.uv_pipe_t +--- @return integer +function uv.pipe_pending_count(pipe) end + +--- Returns the pending pipe count for the named pipe. +--- @return integer +function uv_pipe_t:pending_count() end + +--- Used to receive handles over IPC pipes. +--- +--- First - call `uv.pipe_pending_count()`, if it's > 0 then initialize a handle of +--- the given type, returned by `uv.pipe_pending_type()` and call +--- `uv.accept(pipe, handle)`. +--- @param pipe uv.uv_pipe_t +--- @return string +function uv.pipe_pending_type(pipe) end + +--- Used to receive handles over IPC pipes. +--- +--- First - call `uv.pipe_pending_count()`, if it's > 0 then initialize a handle of +--- the given type, returned by `uv.pipe_pending_type()` and call +--- `uv.accept(pipe, handle)`. +--- @return string +function uv_pipe_t:pending_type() end + +--- Alters pipe permissions, allowing it to be accessed from processes run by different users. +--- Makes the pipe writable or readable by all users. `flags` are: `"r"`, `"w"`, `"rw"`, or `"wr"` +--- where `r` is `READABLE` and `w` is `WRITABLE`. This function is blocking. +--- @param pipe uv.uv_pipe_t +--- @param flags string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_chmod(pipe, flags) end + +--- Alters pipe permissions, allowing it to be accessed from processes run by different users. +--- Makes the pipe writable or readable by all users. `flags` are: `"r"`, `"w"`, `"rw"`, or `"wr"` +--- where `r` is `READABLE` and `w` is `WRITABLE`. This function is blocking. +--- @param flags string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:chmod(flags) end + +--- @class uv.pipe.fds +--- +--- (file descriptor) +--- @field read integer +--- +--- (file descriptor) +--- @field write integer + +--- Create a pair of connected pipe handles. Data may be written to the `write` fd and read from the `read` fd. The resulting handles can be passed to `pipe_open`, used with `spawn`, or for any other purpose. +--- +--- Flags: +--- - `nonblock`: Opens the specified socket handle for `OVERLAPPED` or `FIONBIO`/`O_NONBLOCK` I/O usage. This is recommended for handles that will be used by libuv, and not usually recommended otherwise. +--- +--- Equivalent to `pipe(2)` with the `O_CLOEXEC` flag set. +--- Example +--- ```lua +--- -- Simple read/write with pipe_open +--- local fds = uv.pipe({nonblock=true}, {nonblock=true}) +--- +--- local read_pipe = uv.new_pipe() +--- read_pipe:open(fds.read) +--- +--- local write_pipe = uv.new_pipe() +--- write_pipe:open(fds.write) +--- +--- write_pipe:write("hello") +--- read_pipe:read_start(function(err, chunk) +--- assert(not err, err) +--- print(chunk) +--- end) +--- ``` +--- @param read_flags { nonblock: boolean }? +--- @param write_flags { nonblock: boolean }? +--- @return uv.pipe.fds? fds +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe(read_flags, write_flags) end + +--- Bind the pipe to a file path (Unix) or a name (Windows). +--- +--- `Flags`: +--- +--- - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. +--- - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. +--- - If `type(flags)` is `nil`, it use default value `0`. +--- - Returns `EINVAL` for unsupported flags without performing the bind operation. +--- +--- Supports Linux abstract namespace sockets. namelen must include the leading '\0' byte but not the trailing nul byte. +--- **Note**: +--- 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- 2. New in version 1.46.0. +--- @param pipe uv.uv_pipe_t +--- @param name string +--- @param flags integer|table? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_bind2(pipe, name, flags) end + +--- Bind the pipe to a file path (Unix) or a name (Windows). +--- +--- `Flags`: +--- +--- - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. +--- - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. +--- - If `type(flags)` is `nil`, it use default value `0`. +--- - Returns `EINVAL` for unsupported flags without performing the bind operation. +--- +--- Supports Linux abstract namespace sockets. namelen must include the leading '\0' byte but not the trailing nul byte. +--- **Note**: +--- 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- 2. New in version 1.46.0. +--- @param name string +--- @param flags integer|table? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:bind2(name, flags) end + +--- Connect to the Unix domain socket or the named pipe. +--- +--- `Flags`: +--- +--- - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. +--- - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. +--- - If `type(flags)` is `nil`, it use default value `0`. +--- - Returns `EINVAL` for unsupported flags without performing the bind operation. +--- +--- Supports Linux abstract namespace sockets. namelen must include the leading nul byte but not the trailing nul byte. +--- **Note**: +--- 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- 2. New in version 1.46.0. +--- @param pipe uv.uv_pipe_t +--- @param name string +--- @param flags integer|table? +--- @param callback fun(err: string?)? +--- @return uv.uv_connect_t? connect +--- @return string? err +--- @return uv.error_name? err_name +function uv.pipe_connect2(pipe, name, flags, callback) end + +--- Connect to the Unix domain socket or the named pipe. +--- +--- `Flags`: +--- +--- - If `type(flags)` is `number`, it must be `0` or `uv.constants.PIPE_NO_TRUNCATE`. +--- - If `type(flags)` is `table`, it must be `{}` or `{ no_truncate = true|false }`. +--- - If `type(flags)` is `nil`, it use default value `0`. +--- - Returns `EINVAL` for unsupported flags without performing the bind operation. +--- +--- Supports Linux abstract namespace sockets. namelen must include the leading nul byte but not the trailing nul byte. +--- **Note**: +--- 1. Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +--- typically between 92 and 108 bytes. +--- 2. New in version 1.46.0. +--- @param name string +--- @param flags integer|table? +--- @param callback fun(err: string?)? +--- @return uv.uv_connect_t? connect +--- @return string? err +--- @return uv.error_name? err_name +function uv_pipe_t:connect2(name, flags, callback) end + + +--- # `uv_tty_t` - TTY handle +--- +--- > [`uv_handle_t`][] and [`uv_stream_t`][] functions also apply. +--- +--- TTY handles represent a stream for the console. +--- +--- ```lua +--- -- Simple echo program +--- local stdin = uv.new_tty(0, true) +--- local stdout = uv.new_tty(1, false) +--- +--- stdin:read_start(function (err, data) +--- assert(not err, err) +--- if data then +--- stdout:write(data) +--- else +--- stdin:close() +--- stdout:close() +--- end +--- end) +--- ``` +--- @class uv.uv_tty_t : uv.uv_stream_t +local uv_tty_t = {} + +--- Initialize a new TTY stream with the given file descriptor. Usually the file +--- descriptor will be: +--- +--- - 0 - stdin +--- - 1 - stdout +--- - 2 - stderr +--- +--- On Unix this function will determine the path of the fd of the terminal using +--- ttyname_r(3), open it, and use it if the passed file descriptor refers to a TTY. +--- This lets libuv put the tty in non-blocking mode without affecting other +--- processes that share the tty. +--- +--- This function is not thread safe on systems that don’t support ioctl TIOCGPTN or TIOCPTYGNAME, for instance OpenBSD and Solaris. +--- **Note**: +--- If reopening the TTY fails, libuv falls back to blocking writes. +--- @param fd integer +--- @param readable boolean +--- @return uv.uv_tty_t? tty +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_tty(fd, readable) end + +--- Set the TTY using the specified terminal mode. +--- +--- See [Constants][] for supported TTY mode input values. +--- @param tty uv.uv_tty_t +--- @param mode string|integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tty_set_mode(tty, mode) end + +--- Set the TTY using the specified terminal mode. +--- +--- See [Constants][] for supported TTY mode input values. +--- @param mode string|integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_tty_t:set_mode(mode) end + +--- To be called when the program exits. Resets TTY settings to default values for +--- the next process to take over. +--- +--- This function is async signal-safe on Unix platforms but can fail with error +--- code `EBUSY` if you call it when execution is inside `uv.tty_set_mode()`. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.tty_reset_mode() end + +--- Gets the current Window width and height. +--- @param tty uv.uv_tty_t +--- @return integer? width +--- @return integer|string height_or_err +--- @return uv.error_name? err_name +function uv.tty_get_winsize(tty) end + +--- Gets the current Window width and height. +--- @return integer? width +--- @return integer|string height_or_err +--- @return uv.error_name? err_name +function uv_tty_t:get_winsize() end + +--- Controls whether console virtual terminal sequences are processed by libuv or +--- console. Useful in particular for enabling ConEmu support of ANSI X3.64 and +--- Xterm 256 colors. Otherwise Windows10 consoles are usually detected +--- automatically. State should be one of: `"supported"` or `"unsupported"`. +--- +--- This function is only meaningful on Windows systems. On Unix it is silently +--- ignored. +--- @param state string +function uv.tty_set_vterm_state(state) end + +--- Get the current state of whether console virtual terminal sequences are handled +--- by libuv or the console. The return value is `"supported"` or `"unsupported"`. +--- +--- This function is not implemented on Unix, where it returns `ENOTSUP`. +--- @return string? state +--- @return string? err +--- @return uv.error_name? err_name +function uv.tty_get_vterm_state() end + + +--- # `uv_udp_t` - UDP handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- UDP handles encapsulate UDP communication for both clients and servers. +--- @class uv.uv_udp_t : uv.uv_handle_t +local uv_udp_t = {} + +--- Creates and initializes a new `uv_udp_t`. Returns the Lua userdata wrapping +--- it. The actual socket is created lazily. +--- +--- See [Constants][] for supported address `family` input values. +--- +--- When specified, `mmsgs` determines the number of messages able to be received +--- at one time via `recvmmsg(2)` (the allocated buffer will be sized to be able +--- to fit the specified number of max size dgrams). Only has an effect on +--- platforms that support `recvmmsg(2)`. +--- +--- **Note:** For backwards compatibility reasons, `flags` can also be a string or +--- integer. When it is a string, it will be treated like the `family` key above. +--- When it is an integer, it will be used directly as the `flags` parameter when +--- calling `uv_udp_init_ex`. +--- @param flags { family: string?, mmsgs: integer? }? +--- @return uv.uv_udp_t? udp +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_udp(flags) end + +--- Returns the handle's send queue size. +--- @param udp uv.uv_udp_t +--- @return integer +function uv.udp_get_send_queue_size(udp) end + +--- Returns the handle's send queue size. +--- @return integer +function uv_udp_t:get_send_queue_size() end + +--- Returns the handle's send queue count. +--- @param udp uv.uv_udp_t +--- @return integer +function uv.udp_get_send_queue_count(udp) end + +--- Returns the handle's send queue count. +--- @return integer +function uv_udp_t:get_send_queue_count() end + +--- Opens an existing file descriptor or Windows SOCKET as a UDP handle. +--- +--- Unix only: The only requirement of the sock argument is that it follows the +--- datagram contract (works in unconnected mode, supports sendmsg()/recvmsg(), +--- etc). In other words, other datagram-type sockets like raw sockets or netlink +--- sockets can also be passed to this function. +--- +--- The file descriptor is set to non-blocking mode. +--- +--- Note: The passed file descriptor or SOCKET is not checked for its type, but +--- it's required that it represents a valid datagram socket. +--- @param udp uv.uv_udp_t +--- @param fd integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_open(udp, fd) end + +--- Opens an existing file descriptor or Windows SOCKET as a UDP handle. +--- +--- Unix only: The only requirement of the sock argument is that it follows the +--- datagram contract (works in unconnected mode, supports sendmsg()/recvmsg(), +--- etc). In other words, other datagram-type sockets like raw sockets or netlink +--- sockets can also be passed to this function. +--- +--- The file descriptor is set to non-blocking mode. +--- +--- Note: The passed file descriptor or SOCKET is not checked for its type, but +--- it's required that it represents a valid datagram socket. +--- @param fd integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:open(fd) end + +--- Bind the UDP handle to an IP address and port. Any `flags` are set with a table +--- with fields `reuseaddr` or `ipv6only` equal to `true` or `false`. +--- @param udp uv.uv_udp_t +--- @param host string +--- @param port number +--- @param flags { ipv6only: boolean?, reuseaddr: boolean? }? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_bind(udp, host, port, flags) end + +--- Bind the UDP handle to an IP address and port. Any `flags` are set with a table +--- with fields `reuseaddr` or `ipv6only` equal to `true` or `false`. +--- @param host string +--- @param port number +--- @param flags { ipv6only: boolean?, reuseaddr: boolean? }? +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:bind(host, port, flags) end + +--- Get the local IP and port of the UDP handle. +--- @param udp uv.uv_udp_t +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_getsockname(udp) end + +--- Get the local IP and port of the UDP handle. +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:getsockname() end + +--- Get the remote IP and port of the UDP handle on connected UDP handles. +--- @param udp uv.uv_udp_t +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_getpeername(udp) end + +--- Get the remote IP and port of the UDP handle on connected UDP handles. +--- @return uv.socketinfo? address +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:getpeername() end + +--- Set membership for a multicast address. `multicast_addr` is multicast address to +--- set membership for. `interface_addr` is interface address. `membership` can be +--- the string `"leave"` or `"join"`. +--- @param udp uv.uv_udp_t +--- @param multicast_addr string +--- @param interface_addr string? +--- @param membership string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_set_membership(udp, multicast_addr, interface_addr, membership) end + +--- Set membership for a multicast address. `multicast_addr` is multicast address to +--- set membership for. `interface_addr` is interface address. `membership` can be +--- the string `"leave"` or `"join"`. +--- @param multicast_addr string +--- @param interface_addr string? +--- @param membership string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:set_membership(multicast_addr, interface_addr, membership) end + +--- Set membership for a source-specific multicast group. `multicast_addr` is multicast +--- address to set membership for. `interface_addr` is interface address. `source_addr` +--- is source address. `membership` can be the string `"leave"` or `"join"`. +--- @param udp uv.uv_udp_t +--- @param multicast_addr string +--- @param interface_addr string? +--- @param source_addr string +--- @param membership string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_set_source_membership(udp, multicast_addr, interface_addr, source_addr, membership) end + +--- Set membership for a source-specific multicast group. `multicast_addr` is multicast +--- address to set membership for. `interface_addr` is interface address. `source_addr` +--- is source address. `membership` can be the string `"leave"` or `"join"`. +--- @param multicast_addr string +--- @param interface_addr string? +--- @param source_addr string +--- @param membership string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:set_source_membership(multicast_addr, interface_addr, source_addr, membership) end + +--- Set IP multicast loop flag. Makes multicast packets loop back to local +--- sockets. +--- @param udp uv.uv_udp_t +--- @param on boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_set_multicast_loop(udp, on) end + +--- Set IP multicast loop flag. Makes multicast packets loop back to local +--- sockets. +--- @param on boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:set_multicast_loop(on) end + +--- Set the multicast ttl. +--- +--- `ttl` is an integer 1 through 255. +--- @param udp uv.uv_udp_t +--- @param ttl integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_set_multicast_ttl(udp, ttl) end + +--- Set the multicast ttl. +--- +--- `ttl` is an integer 1 through 255. +--- @param ttl integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:set_multicast_ttl(ttl) end + +--- Set the multicast interface to send or receive data on. +--- @param udp uv.uv_udp_t +--- @param interface_addr string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_set_multicast_interface(udp, interface_addr) end + +--- Set the multicast interface to send or receive data on. +--- @param interface_addr string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:set_multicast_interface(interface_addr) end + +--- Set broadcast on or off. +--- @param udp uv.uv_udp_t +--- @param on boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_set_broadcast(udp, on) end + +--- Set broadcast on or off. +--- @param on boolean +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:set_broadcast(on) end + +--- Set the time to live. +--- +--- `ttl` is an integer 1 through 255. +--- @param udp uv.uv_udp_t +--- @param ttl integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_set_ttl(udp, ttl) end + +--- Set the time to live. +--- +--- `ttl` is an integer 1 through 255. +--- @param ttl integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:set_ttl(ttl) end + +--- Send data over the UDP socket. If the socket has not previously been bound +--- with `uv.udp_bind()` it will be bound to `0.0.0.0` (the "all interfaces" IPv4 +--- address) and a random port number. +--- @param udp uv.uv_udp_t +--- @param data uv.buffer +--- @param host string +--- @param port integer +--- @param callback fun(err: string?) +--- @return uv.uv_udp_send_t? send +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_send(udp, data, host, port, callback) end + +--- Send data over the UDP socket. If the socket has not previously been bound +--- with `uv.udp_bind()` it will be bound to `0.0.0.0` (the "all interfaces" IPv4 +--- address) and a random port number. +--- @param data uv.buffer +--- @param host string +--- @param port integer +--- @param callback fun(err: string?) +--- @return uv.uv_udp_send_t? send +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:send(data, host, port, callback) end + +--- Same as `uv.udp_send()`, but won't queue a send request if it can't be +--- completed immediately. +--- @param udp uv.uv_udp_t +--- @param data uv.buffer +--- @param host string +--- @param port integer +--- @return integer? bytes_sent +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_try_send(udp, data, host, port) end + +--- Same as `uv.udp_send()`, but won't queue a send request if it can't be +--- completed immediately. +--- @param data uv.buffer +--- @param host string +--- @param port integer +--- @return integer? bytes_sent +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:try_send(data, host, port) end + +--- Like `uv.udp_try_send()`, but can send multiple datagrams. +--- Lightweight abstraction around `sendmmsg(2)`, with a `sendmsg(2)` fallback loop +--- for platforms that do not support the former. The `udp` handle must be fully +--- initialized, either from a `uv.udp_bind` call, another call that will bind +--- automatically (`udp_send`, `udp_try_send`, etc), or from `uv.udp_connect`. +--- +--- `messages` should be an array-like table, where `addr` must be specified +--- if the `udp` has not been connected via `udp_connect`. Otherwise, `addr` +--- must be `nil`. +--- +--- `flags` is reserved for future extension and must currently be `nil` or `0` or +--- `{}`. +--- +--- Returns the number of messages sent successfully. An error will only be returned +--- if the first datagram failed to be sent. +--- Example +--- ```lua +--- -- If client:connect(...) was not called +--- local addr = { ip = "127.0.0.1", port = 1234 } +--- client:try_send2({ +--- { data = "Message 1", addr = addr }, +--- { data = "Message 2", addr = addr }, +--- }) +--- +--- -- If client:connect(...) was called +--- client:try_send2({ +--- { data = "Message 1" }, +--- { data = "Message 2" }, +--- }) +--- ``` +--- @param udp uv.uv_udp_t +--- @param messages table +--- @param flags 0|{}? +--- @param port integer +--- @return integer? messages_sent +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_try_send2(udp, messages, flags, port) end + +--- Like `uv.udp_try_send()`, but can send multiple datagrams. +--- Lightweight abstraction around `sendmmsg(2)`, with a `sendmsg(2)` fallback loop +--- for platforms that do not support the former. The `udp` handle must be fully +--- initialized, either from a `uv.udp_bind` call, another call that will bind +--- automatically (`udp_send`, `udp_try_send`, etc), or from `uv.udp_connect`. +--- +--- `messages` should be an array-like table, where `addr` must be specified +--- if the `udp` has not been connected via `udp_connect`. Otherwise, `addr` +--- must be `nil`. +--- +--- `flags` is reserved for future extension and must currently be `nil` or `0` or +--- `{}`. +--- +--- Returns the number of messages sent successfully. An error will only be returned +--- if the first datagram failed to be sent. +--- Example +--- ```lua +--- -- If client:connect(...) was not called +--- local addr = { ip = "127.0.0.1", port = 1234 } +--- client:try_send2({ +--- { data = "Message 1", addr = addr }, +--- { data = "Message 2", addr = addr }, +--- }) +--- +--- -- If client:connect(...) was called +--- client:try_send2({ +--- { data = "Message 1" }, +--- { data = "Message 2" }, +--- }) +--- ``` +--- @param messages table +--- @param flags 0|{}? +--- @param port integer +--- @return integer? messages_sent +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:try_send2(messages, flags, port) end + +--- @alias uv.udp_recv_start.callback +--- | fun(err: string?, data: string?, addr: uv.udp_recv_start.callback.addr?, flags: { partial: boolean?, mmsg_chunk: boolean? }) + +--- @class uv.udp_recv_start.callback.addr +--- @field ip string +--- @field port integer +--- @field family string + +--- Prepare for receiving data. If the socket has not previously been bound with +--- `uv.udp_bind()` it is bound to `0.0.0.0` (the "all interfaces" IPv4 address) +--- and a random port number. +--- +--- See [Constants][] for supported address `family` output values. +--- @param udp uv.uv_udp_t +--- @param callback uv.udp_recv_start.callback +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_recv_start(udp, callback) end + +--- Prepare for receiving data. If the socket has not previously been bound with +--- `uv.udp_bind()` it is bound to `0.0.0.0` (the "all interfaces" IPv4 address) +--- and a random port number. +--- +--- See [Constants][] for supported address `family` output values. +--- @param callback uv.udp_recv_start.callback +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:recv_start(callback) end + +--- Stop listening for incoming datagrams. +--- @param udp uv.uv_udp_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_recv_stop(udp) end + +--- Stop listening for incoming datagrams. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:recv_stop() end + +--- Associate the UDP handle to a remote address and port, so every message sent by +--- this handle is automatically sent to that destination. Calling this function +--- with a NULL addr disconnects the handle. Trying to call `uv.udp_connect()` on an +--- already connected handle will result in an `EISCONN` error. Trying to disconnect +--- a handle that is not connected will return an `ENOTCONN` error. +--- @param udp uv.uv_udp_t +--- @param host string +--- @param port integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.udp_connect(udp, host, port) end + +--- Associate the UDP handle to a remote address and port, so every message sent by +--- this handle is automatically sent to that destination. Calling this function +--- with a NULL addr disconnects the handle. Trying to call `uv.udp_connect()` on an +--- already connected handle will result in an `EISCONN` error. Trying to disconnect +--- a handle that is not connected will return an `ENOTCONN` error. +--- @param host string +--- @param port integer +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_udp_t:connect(host, port) end + + +--- # `uv_fs_event_t` - FS Event handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- FS Event handles allow the user to monitor a given path for changes, for +--- example, if the file was renamed or there was a generic change in it. This +--- handle uses the best backend for the job on each platform. +--- @class uv.uv_fs_event_t : uv.uv_handle_t +local uv_fs_event_t = {} + +--- Creates and initializes a new `uv_fs_event_t`. Returns the Lua userdata wrapping +--- it. +--- @return uv.uv_fs_event_t? fs_event +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_fs_event() end + +--- @alias uv.fs_event_start.callback +--- | fun(err: string?, filename: string, events: { change: boolean?, rename: boolean? }) + +--- @class uv.fs_event_start.flags +--- @field watch_entry boolean? +--- @field stat boolean? +--- @field recursive boolean? + +--- Start the handle with the given callback, which will watch the specified path +--- for changes. +--- @param fs_event uv.uv_fs_event_t +--- @param path string +--- @param flags uv.fs_event_start.flags +--- @param callback uv.fs_event_start.callback +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.fs_event_start(fs_event, path, flags, callback) end + +--- Start the handle with the given callback, which will watch the specified path +--- for changes. +--- @param path string +--- @param flags uv.fs_event_start.flags +--- @param callback uv.fs_event_start.callback +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_fs_event_t:start(path, flags, callback) end + +--- Stop the handle, the callback will no longer be called. +--- @param fs_event uv.uv_fs_event_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.fs_event_stop(fs_event) end + +--- Stop the handle, the callback will no longer be called. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_fs_event_t:stop() end + +--- Get the path being monitored by the handle. +--- @param fs_event uv.uv_fs_event_t +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv.fs_event_getpath(fs_event) end + +--- Get the path being monitored by the handle. +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv_fs_event_t:getpath() end + + +--- # `uv_fs_poll_t` - FS Poll handle +--- +--- > [`uv_handle_t`][] functions also apply. +--- +--- FS Poll handles allow the user to monitor a given path for changes. Unlike +--- `uv_fs_event_t`, fs poll handles use `stat` to detect when a file has changed so +--- they can work on file systems where fs event handles can't. +--- @class uv.uv_fs_poll_t : uv.uv_handle_t +local uv_fs_poll_t = {} + +--- Creates and initializes a new `uv_fs_poll_t`. Returns the Lua userdata wrapping +--- it. +--- @return uv.uv_fs_poll_t? fs_poll +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_fs_poll() end + +--- @alias uv.fs_poll_start.callback +--- | fun(err: string?, prev: table?, curr: table?) + +--- Check the file at `path` for changes every `interval` milliseconds. +--- +--- **Note:** For maximum portability, use multi-second intervals. Sub-second +--- intervals will not detect all changes on many file systems. +--- @param fs_poll uv.uv_fs_poll_t +--- @param path string +--- @param interval integer +--- @param callback uv.fs_poll_start.callback +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.fs_poll_start(fs_poll, path, interval, callback) end + +--- Check the file at `path` for changes every `interval` milliseconds. +--- +--- **Note:** For maximum portability, use multi-second intervals. Sub-second +--- intervals will not detect all changes on many file systems. +--- @param path string +--- @param interval integer +--- @param callback uv.fs_poll_start.callback +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_fs_poll_t:start(path, interval, callback) end + +--- Stop the handle, the callback will no longer be called. +--- @param fs_poll uv.uv_fs_poll_t +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.fs_poll_stop(fs_poll) end + +--- Stop the handle, the callback will no longer be called. +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv_fs_poll_t:stop() end + +--- Get the path being monitored by the handle. +--- @param fs_poll uv.uv_fs_poll_t +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv.fs_poll_getpath(fs_poll) end + +--- Get the path being monitored by the handle. +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv_fs_poll_t:getpath() end + + +--- # File system operations +--- +--- Most file system functions can operate synchronously or asynchronously. When a synchronous version is called (by omitting a callback), the function will +--- immediately return the results of the FS call. When an asynchronous version is +--- called (by providing a callback), the function will immediately return a +--- `uv_fs_t userdata` and asynchronously execute its callback; if an error is encountered, the first and only argument passed to the callback will be the `err` error string; if the operation completes successfully, the first argument will be `nil` and the remaining arguments will be the results of the FS call. +--- +--- Synchronous and asynchronous versions of `readFile` (with naive error handling) +--- are implemented below as an example: +--- +--- ```lua +--- local function readFileSync(path) +--- local fd = assert(uv.fs_open(path, "r", 438)) +--- local stat = assert(uv.fs_fstat(fd)) +--- local data = assert(uv.fs_read(fd, stat.size, 0)) +--- assert(uv.fs_close(fd)) +--- return data +--- end +--- +--- local data = readFileSync("main.lua") +--- print("synchronous read", data) +--- ``` +--- +--- ```lua +--- local function readFile(path, callback) +--- uv.fs_open(path, "r", 438, function(err, fd) +--- assert(not err, err) +--- uv.fs_fstat(fd, function(err, stat) +--- assert(not err, err) +--- uv.fs_read(fd, stat.size, 0, function(err, data) +--- assert(not err, err) +--- uv.fs_close(fd, function(err) +--- assert(not err, err) +--- return callback(data) +--- end) +--- end) +--- end) +--- end) +--- end +--- +--- readFile("main.lua", function(data) +--- print("asynchronous read", data) +--- end) +--- ``` + +--- Equivalent to `close(2)`. +--- @param fd integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_close(fd) end + +--- Equivalent to `open(2)`. Access `flags` may be an integer or one of: `"r"`, +--- `"rs"`, `"sr"`, `"r+"`, `"rs+"`, `"sr+"`, `"w"`, `"wx"`, `"xw"`, `"w+"`, +--- `"wx+"`, `"xw+"`, `"a"`, `"ax"`, `"xa"`, `"a+"`, `"ax+"`, or "`xa+`". +--- **Note**: +--- On Windows, libuv uses `CreateFileW` and thus the file is always +--- opened in binary mode. Because of this, the `O_BINARY` and `O_TEXT` flags are +--- not supported. +--- @param path string +--- @param flags string|integer +--- @param mode integer (octal `chmod(1)` mode, e.g. `tonumber('644', 8)`) +--- @return integer? fd +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, flags: string|integer, mode: integer, callback: fun(err: string?, fd: integer?)): uv.uv_fs_t +function uv.fs_open(path, flags, mode) end + +--- Equivalent to `preadv(2)`. Returns any data. An empty string indicates EOF. +--- +--- If `offset` is nil or omitted, it will default to `-1`, which indicates 'use and update the current file offset.' +--- +--- **Note:** When `offset` is >= 0, the current file offset will not be updated by the read. +--- @param fd integer +--- @param size integer +--- @param offset integer? +--- @return string? data +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, size: integer, offset: integer?, callback: fun(err: string?, data: string?)): uv.uv_fs_t +function uv.fs_read(fd, size, offset) end + +--- Equivalent to `unlink(2)`. +--- @param path string +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_unlink(path) end + +--- Equivalent to `pwritev(2)`. Returns the number of bytes written. +--- +--- If `offset` is nil or omitted, it will default to `-1`, which indicates 'use and update the current file offset.' +--- +--- **Note:** When `offset` is >= 0, the current file offset will not be updated by the write. +--- @param fd integer +--- @param data uv.buffer +--- @param offset integer? +--- @return integer? bytes_written +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, data: uv.buffer, offset: integer?, callback: fun(err: string?, bytes: integer?)): uv.uv_fs_t +function uv.fs_write(fd, data, offset) end + +--- Equivalent to `mkdir(2)`. +--- @param path string +--- @param mode integer (octal `chmod(1)` mode, e.g. `tonumber('755', 8)`) +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, mode: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_mkdir(path, mode) end + +--- Equivalent to `mkdtemp(3)`. +--- @param template string +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(template: string, callback: fun(err: string?, path: string?)): uv.uv_fs_t +function uv.fs_mkdtemp(template) end + +--- @alias uv.fs_mkstemp.callback +--- | fun(err: string?, fd: integer?, path: string?) + +--- Equivalent to `mkstemp(3)`. Returns a temporary file handle and filename. +--- @param template string +--- @return integer? fd +--- @return string path_or_err +--- @return uv.error_name? err_name +--- @overload fun(template: string, callback: uv.fs_mkstemp.callback): uv.uv_fs_t +function uv.fs_mkstemp(template) end + +--- Equivalent to `rmdir(2)`. +--- @param path string +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_rmdir(path) end + +--- Equivalent to `scandir(3)`, with a slightly different API. Returns a handle that +--- the user can pass to `uv.fs_scandir_next()`. +--- +--- **Note:** This function can be used synchronously or asynchronously. The request +--- userdata is always synchronously returned regardless of whether a callback is +--- provided and the same userdata is passed to the callback if it is provided. +--- @param path string +--- @param callback fun(err: string?, success: uv.uv_fs_t?)? +--- @return uv.uv_fs_t? handle +--- @return string? err +--- @return uv.error_name? err_name +function uv.fs_scandir(path, callback) end + +--- Called on a `uv_fs_t` returned by `uv.fs_scandir()` to get the next directory +--- entry data as a `name, type` pair. When there are no more entries, `nil` is +--- returned. +--- +--- **Note:** This function only has a synchronous version. See `uv.fs_opendir` and +--- its related functions for an asynchronous version. +--- @param fs uv.uv_fs_t +--- @return string? name +--- @return string type_or_err +--- @return uv.error_name? err_name +function uv.fs_scandir_next(fs) end + +--- @class uv.fs_stat.result +--- @field dev integer +--- @field mode integer +--- @field nlink integer +--- @field uid integer +--- @field gid integer +--- @field rdev integer +--- @field ino integer +--- @field size integer +--- @field blksize integer +--- @field blocks integer +--- @field flags integer +--- @field gen integer +--- @field atime uv.fs_stat.result.time +--- @field mtime uv.fs_stat.result.time +--- @field ctime uv.fs_stat.result.time +--- @field birthtime uv.fs_stat.result.time +--- @field type string + +--- @class uv.fs_stat.result.time +--- @field sec integer +--- @field nsec integer + +--- @class uv.fs_statfs.result +--- @field type integer +--- @field bsize integer +--- @field blocks integer +--- @field bfree integer +--- @field bavail integer +--- @field files integer +--- @field ffree integer + +--- Equivalent to `stat(2)`. +--- @param path string +--- @return uv.fs_stat.result? stat +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, stat: uv.fs_stat.result?)): uv.uv_fs_t +function uv.fs_stat(path) end + +--- Equivalent to `fstat(2)`. +--- @param fd integer +--- @return uv.fs_stat.result? stat +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, callback: fun(err: string?, stat: uv.fs_stat.result?)): uv.uv_fs_t +function uv.fs_fstat(fd) end + +--- Equivalent to `lstat(2)`. +--- @param path string +--- @return uv.fs_stat.result? stat +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, stat: uv.fs_stat.result?)): uv.uv_fs_t +function uv.fs_lstat(path) end + +--- Equivalent to `rename(2)`. +--- @param path string +--- @param new_path string +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, new_path: string, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_rename(path, new_path) end + +--- Equivalent to `fsync(2)`. +--- @param fd integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_fsync(fd) end + +--- Equivalent to `fdatasync(2)`. +--- @param fd integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_fdatasync(fd) end + +--- Equivalent to `ftruncate(2)`. +--- @param fd integer +--- @param offset integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, offset: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_ftruncate(fd, offset) end + +--- Limited equivalent to `sendfile(2)`. Returns the number of bytes written. +--- @param out_fd integer +--- @param in_fd integer +--- @param in_offset integer +--- @param size integer +--- @return integer? bytes +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(out_fd: integer, in_fd: integer, in_offset: integer, size: integer, callback: fun(err: string?, bytes: integer?)): uv.uv_fs_t +function uv.fs_sendfile(out_fd, in_fd, in_offset, size) end + +--- Equivalent to `access(2)` on Unix. Windows uses `GetFileAttributesW()`. Access +--- `mode` can be an integer or a string containing `"R"` or `"W"` or `"X"`. +--- Returns `true` or `false` indicating access permission. +--- @param path string +--- @param mode string (a combination of the `'r'`, `'w'` and `'x'` characters denoting the symbolic mode as per `chmod(1)`) +--- @return boolean? permission +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, mode: string, callback: fun(err: string?, permission: boolean?)): uv.uv_fs_t +function uv.fs_access(path, mode) end + +--- Equivalent to `chmod(2)`. +--- @param path string +--- @param mode integer (octal `chmod(1)` mode, e.g. `tonumber('644', 8)`) +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, mode: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_chmod(path, mode) end + +--- Equivalent to `fchmod(2)`. +--- @param fd integer +--- @param mode integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, mode: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_fchmod(fd, mode) end + +--- Equivalent to `utime(2)`. +--- @param path string +--- @param atime number +--- @param mtime number +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, atime: number, mtime: number, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_utime(path, atime, mtime) end + +--- Equivalent to `futime(2)`. +--- @param fd integer +--- @param atime number +--- @param mtime number +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, atime: number, mtime: number, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_futime(fd, atime, mtime) end + +--- Equivalent to `lutime(2)`. +--- @param path string +--- @param atime number +--- @param mtime number +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, atime: number, mtime: number, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_lutime(path, atime, mtime) end + +--- Equivalent to `link(2)`. +--- @param path string +--- @param new_path string +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, new_path: string, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_link(path, new_path) end + +--- Equivalent to `symlink(2)`. If the `flags` parameter is omitted, then the 3rd parameter will be treated as the `callback`. +--- @param path string +--- @param new_path string +--- @param flags integer|{ dir: boolean?, junction: boolean? }? +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, new_path: string, flags: integer|{ dir: boolean?, junction: boolean? }?, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_symlink(path, new_path, flags) end + +--- Equivalent to `readlink(2)`. +--- @param path string +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, path: string?)): uv.uv_fs_t +function uv.fs_readlink(path) end + +--- Equivalent to `realpath(3)`. +--- @param path string +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, path: string?)): uv.uv_fs_t +function uv.fs_realpath(path) end + +--- Equivalent to `chown(2)`. +--- @param path string +--- @param uid integer +--- @param gid integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, uid: integer, gid: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_chown(path, uid, gid) end + +--- Equivalent to `fchown(2)`. +--- @param fd integer +--- @param uid integer +--- @param gid integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, uid: integer, gid: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_fchown(fd, uid, gid) end + +--- Equivalent to `lchown(2)`. +--- @param fd integer +--- @param uid integer +--- @param gid integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(fd: integer, uid: integer, gid: integer, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_lchown(fd, uid, gid) end + +--- @class uv.fs_copyfile.flags +--- @field excl boolean? +--- @field ficlone boolean? +--- @field ficlone_force boolean? + +--- Copies a file from path to new_path. If the `flags` parameter is omitted, then the 3rd parameter will be treated as the `callback`. +--- @param path string +--- @param new_path string +--- @param flags integer|uv.fs_copyfile.flags? +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, new_path: string, flags: integer|uv.fs_copyfile.flags?, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_copyfile(path, new_path, flags) end + +--- Opens path as a directory stream. Returns a handle that the user can pass to +--- `uv.fs_readdir()`. The `entries` parameter defines the maximum number of entries +--- that should be returned by each call to `uv.fs_readdir()`. +--- @param path string +--- @param entries integer? +--- @return uv.luv_dir_t? dir +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, dir: uv.luv_dir_t?), entries: integer?): uv.uv_fs_t +function uv.fs_opendir(path, entries) end + +--- Iterates over the directory stream `luv_dir_t` returned by a successful +--- `uv.fs_opendir()` call. A table of data tables is returned where the number +--- of entries `n` is equal to or less than the `entries` parameter used in +--- the associated `uv.fs_opendir()` call. +--- @param dir uv.luv_dir_t +--- @return table? entries +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(dir: uv.luv_dir_t, callback: fun(err: string?, entries: table?)): uv.uv_fs_t +function uv.fs_readdir(dir) end + +--- @class uv.luv_dir_t : userdata +local luv_dir_t = {} + +--- Iterates over the directory stream `luv_dir_t` returned by a successful +--- `uv.fs_opendir()` call. A table of data tables is returned where the number +--- of entries `n` is equal to or less than the `entries` parameter used in +--- the associated `uv.fs_opendir()` call. +--- @return table? entries +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(dir: uv.luv_dir_t, callback: fun(err: string?, entries: table?)): uv.uv_fs_t +function luv_dir_t:readdir() end + +--- Closes a directory stream returned by a successful `uv.fs_opendir()` call. +--- @param dir uv.luv_dir_t +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(dir: uv.luv_dir_t, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function uv.fs_closedir(dir) end + +--- Closes a directory stream returned by a successful `uv.fs_opendir()` call. +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(dir: uv.luv_dir_t, callback: fun(err: string?, success: boolean?)): uv.uv_fs_t +function luv_dir_t:closedir() end + +--- Equivalent to `statfs(2)`. +--- @param path string +--- @return uv.fs_statfs.result? stat +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(path: string, callback: fun(err: string?, stat: uv.fs_statfs.result?)): uv.uv_fs_t +function uv.fs_statfs(path) end + + +--- # Thread pool work scheduling +--- +--- Libuv provides a threadpool which can be used to run user code and get notified +--- in the loop thread. This threadpool is internally used to run all file system +--- operations, as well as `getaddrinfo` and `getnameinfo` requests. +--- +--- ```lua +--- local function work_callback(a, b) +--- return a + b +--- end +--- +--- local function after_work_callback(c) +--- print("The result is: " .. c) +--- end +--- +--- local work = uv.new_work(work_callback, after_work_callback) +--- +--- work:queue(1, 2) +--- +--- -- output: "The result is: 3" +--- ``` + +--- Creates and initializes a new `luv_work_ctx_t` (not `uv_work_t`). +--- `work_callback` is a Lua function or a string containing Lua code or bytecode dumped from a function. +--- Returns the Lua userdata wrapping it. +--- @param work_callback string|fun(...: uv.threadargs) +--- @param after_work_callback fun(...: uv.threadargs) +--- @return uv.luv_work_ctx_t +function uv.new_work(work_callback, after_work_callback) end + +--- Queues a work request which will run `work_callback` in a new Lua state in a +--- thread from the threadpool with any additional arguments from `...`. Values +--- returned from `work_callback` are passed to `after_work_callback`, which is +--- called in the main loop thread. +--- @param work_ctx uv.luv_work_ctx_t +--- @param ... uv.threadargs +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.queue_work(work_ctx, ...) end + +--- @class uv.luv_work_ctx_t : userdata +local luv_work_ctx_t = {} + +--- Queues a work request which will run `work_callback` in a new Lua state in a +--- thread from the threadpool with any additional arguments from `...`. Values +--- returned from `work_callback` are passed to `after_work_callback`, which is +--- called in the main loop thread. +--- @param ... uv.threadargs +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function luv_work_ctx_t:queue(...) end + + +--- # DNS utility functions + +--- @class uv.getaddrinfo.hints +--- @field family string|integer? +--- @field socktype string|integer? +--- @field protocol string|integer? +--- @field addrconfig boolean? +--- @field v4mapped boolean? +--- @field all boolean? +--- @field numerichost boolean? +--- @field passive boolean? +--- @field numericserv boolean? +--- @field canonname boolean? + +--- Equivalent to `getaddrinfo(3)`. Either `node` or `service` may be `nil` but not +--- both. +--- +--- See [Constants][] for supported address `family` input and output values. +--- +--- See [Constants][] for supported `socktype` input and output values. +--- +--- When `protocol` is set to 0 or nil, it will be automatically chosen based on the +--- socket's domain and type. When `protocol` is specified as a string, it will be +--- looked up using the `getprotobyname(3)` function. Examples: `"ip"`, `"icmp"`, +--- `"tcp"`, `"udp"`, etc. +--- @param host string? +--- @param service string? +--- @param hints uv.getaddrinfo.hints? +--- @return table? addresses +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(host: string?, service: string?, hints: uv.getaddrinfo.hints?, callback: fun(err: string?, addresses: table?)): uv.uv_getaddrinfo_t?, string?, uv.error_name? +function uv.getaddrinfo(host, service, hints) end + +--- @class uv.getnameinfo.address +--- @field ip string? +--- @field port integer? +--- @field family string|integer? + +--- @alias uv.getnameinfo.callback +--- | fun(err: string?, host: string?, service: string?) + +--- Equivalent to `getnameinfo(3)`. +--- +--- See [Constants][] for supported address `family` input values. +--- @param address uv.getnameinfo.address +--- @return string? host +--- @return string service_or_err +--- @return uv.error_name? err_name +--- @overload fun(address: uv.getnameinfo.address, callback: uv.getnameinfo.callback): uv.uv_getnameinfo_t?, string?, uv.error_name? +function uv.getnameinfo(address) end + + +--- # Threading and synchronization utilities +--- +--- Libuv provides cross-platform implementations for multiple threading and +--- synchronization primitives. The API largely follows the pthreads API. + +--- Creates and initializes a `luv_thread_t` (not `uv_thread_t`). Returns the Lua +--- userdata wrapping it and asynchronously executes `entry`, which can be either +--- a Lua function or a string containing Lua code or bytecode dumped from a function. Additional arguments `...` +--- are passed to the `entry` function and an optional `options` table may be +--- provided. Currently accepted `option` fields are `stack_size`. +--- **Note**: +--- unsafe, please make sure the thread end of life before Lua state close. +--- @param options { stack_size: integer? }? +--- @param entry function|string +--- @param ... uv.threadargs passed to `entry` +--- @return uv.luv_thread_t? thread +--- @return string? err +--- @return uv.error_name? err_name +function uv.new_thread(options, entry, ...) end + +--- Returns a boolean indicating whether two threads are the same. This function is +--- equivalent to the `__eq` metamethod. +--- @param thread uv.luv_thread_t +--- @param other_thread uv.luv_thread_t +--- @return boolean +function uv.thread_equal(thread, other_thread) end + +--- @class uv.luv_thread_t : userdata +local luv_thread_t = {} + +--- Returns a boolean indicating whether two threads are the same. This function is +--- equivalent to the `__eq` metamethod. +--- @param other_thread uv.luv_thread_t +--- @return boolean +function luv_thread_t:equal(other_thread) end + +--- Sets the specified thread's affinity setting. +--- +--- `affinity` must be a table where each of the keys are a CPU number and the +--- values are booleans that represent whether the `thread` should be eligible to +--- run on that CPU. If the length of the `affinity` table is not greater than or +--- equal to `uv.cpumask_size()`, any CPU numbers missing from the table will have +--- their affinity set to `false`. If setting the affinity of more than +--- `uv.cpumask_size()` CPUs is desired, `affinity` must be an array-like table +--- with no gaps, since `#affinity` will be used as the `cpumask_size` if it is +--- greater than `uv.cpumask_size()`. +--- +--- If `get_old_affinity` is `true`, the previous affinity settings for the `thread` +--- will be returned. Otherwise, `true` is returned after a successful call. +--- +--- **Note:** Thread affinity setting is not atomic on Windows. Unsupported on macOS. +--- @param thread uv.luv_thread_t +--- @param affinity table +--- @param get_old_affinity boolean? +--- @return table? affinity +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_setaffinity(thread, affinity, get_old_affinity) end + +--- Sets the specified thread's affinity setting. +--- +--- `affinity` must be a table where each of the keys are a CPU number and the +--- values are booleans that represent whether the `thread` should be eligible to +--- run on that CPU. If the length of the `affinity` table is not greater than or +--- equal to `uv.cpumask_size()`, any CPU numbers missing from the table will have +--- their affinity set to `false`. If setting the affinity of more than +--- `uv.cpumask_size()` CPUs is desired, `affinity` must be an array-like table +--- with no gaps, since `#affinity` will be used as the `cpumask_size` if it is +--- greater than `uv.cpumask_size()`. +--- +--- If `get_old_affinity` is `true`, the previous affinity settings for the `thread` +--- will be returned. Otherwise, `true` is returned after a successful call. +--- +--- **Note:** Thread affinity setting is not atomic on Windows. Unsupported on macOS. +--- @param affinity table +--- @param get_old_affinity boolean? +--- @return table? affinity +--- @return string? err +--- @return uv.error_name? err_name +function luv_thread_t:setaffinity(affinity, get_old_affinity) end + +--- Gets the specified thread's affinity setting. +--- +--- If `mask_size` is provided, it must be greater than or equal to +--- `uv.cpumask_size()`. If the `mask_size` parameter is omitted, then the return +--- of `uv.cpumask_size()` will be used. Returns an array-like table where each of +--- the keys correspond to a CPU number and the values are booleans that represent +--- whether the `thread` is eligible to run on that CPU. +--- +--- **Note:** Thread affinity getting is not atomic on Windows. Unsupported on macOS. +--- @param thread uv.luv_thread_t +--- @param mask_size integer? +--- @return table? affinity +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_getaffinity(thread, mask_size) end + +--- Gets the specified thread's affinity setting. +--- +--- If `mask_size` is provided, it must be greater than or equal to +--- `uv.cpumask_size()`. If the `mask_size` parameter is omitted, then the return +--- of `uv.cpumask_size()` will be used. Returns an array-like table where each of +--- the keys correspond to a CPU number and the values are booleans that represent +--- whether the `thread` is eligible to run on that CPU. +--- +--- **Note:** Thread affinity getting is not atomic on Windows. Unsupported on macOS. +--- @param mask_size integer? +--- @return table? affinity +--- @return string? err +--- @return uv.error_name? err_name +function luv_thread_t:getaffinity(mask_size) end + +--- Gets the CPU number on which the calling thread is running. +--- +--- **Note:** The first CPU will be returned as the number 1, not 0. This allows for +--- the number to correspond with the table keys used in `uv.thread_getaffinity` and +--- `uv.thread_setaffinity`. +--- @return integer? cpu +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_getcpu() end + +--- Sets the specified thread's scheduling priority setting. It requires elevated +--- privilege to set specific priorities on some platforms. +--- +--- The priority can be set to the following constants. +--- +--- - uv.constants.THREAD_PRIORITY_HIGHEST +--- - uv.constants.THREAD_PRIORITY_ABOVE_NORMAL +--- - uv.constants.THREAD_PRIORITY_NORMAL +--- - uv.constants.THREAD_PRIORITY_BELOW_NORMAL +--- - uv.constants.THREAD_PRIORITY_LOWEST +--- @param thread uv.luv_thread_t +--- @param priority integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_setpriority(thread, priority) end + +--- Sets the specified thread's scheduling priority setting. It requires elevated +--- privilege to set specific priorities on some platforms. +--- +--- The priority can be set to the following constants. +--- +--- - uv.constants.THREAD_PRIORITY_HIGHEST +--- - uv.constants.THREAD_PRIORITY_ABOVE_NORMAL +--- - uv.constants.THREAD_PRIORITY_NORMAL +--- - uv.constants.THREAD_PRIORITY_BELOW_NORMAL +--- - uv.constants.THREAD_PRIORITY_LOWEST +--- @param priority integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function luv_thread_t:setpriority(priority) end + +--- Gets the thread's priority setting. +--- +--- Retrieves the scheduling priority of the specified thread. The returned priority +--- value is platform dependent. +--- +--- For Linux, when schedule policy is SCHED_OTHER (default), priority is 0. +--- @param thread uv.luv_thread_t +--- @return integer? priority +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_getpriority(thread) end + +--- Gets the thread's priority setting. +--- +--- Retrieves the scheduling priority of the specified thread. The returned priority +--- value is platform dependent. +--- +--- For Linux, when schedule policy is SCHED_OTHER (default), priority is 0. +--- @return integer? priority +--- @return string? err +--- @return uv.error_name? err_name +function luv_thread_t:getpriority() end + +--- Returns the handle for the thread in which this is called. +--- @return uv.luv_thread_t +function uv.thread_self() end + +--- Waits for the `thread` to finish executing its entry function. +--- @param thread uv.luv_thread_t +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_join(thread) end + +--- Waits for the `thread` to finish executing its entry function. +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function luv_thread_t:join() end + +--- Detaches a thread. Detached threads automatically release their resources upon +--- termination, eliminating the need for the application to call `uv.thread_join`. +--- @param thread uv.luv_thread_t +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_detach(thread) end + +--- Detaches a thread. Detached threads automatically release their resources upon +--- termination, eliminating the need for the application to call `uv.thread_join`. +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function luv_thread_t:detach() end + +--- Sets the name of the current thread. Different platforms define different limits +--- on the max number of characters a thread name can be: Linux, IBM i (16), macOS +--- (64), Windows (32767), and NetBSD (32), etc. The name will be truncated +--- if `name` is larger than the limit of the platform. +--- @param name string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_setname(name) end + +--- Gets the name of the thread specified by `thread`. +--- @param thread uv.luv_thread_t +--- @return string? name +--- @return string? err +--- @return uv.error_name? err_name +function uv.thread_getname(thread) end + +--- Gets the name of the thread specified by `thread`. +--- @return string? name +--- @return string? err +--- @return uv.error_name? err_name +function luv_thread_t:getname() end + +--- Pauses the thread in which this is called for a number of milliseconds. +--- @param msec integer +function uv.sleep(msec) end + + +--- # Miscellaneous utilities + +--- Returns the executable path. +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv.exepath() end + +--- Returns the current working directory. +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv.cwd() end + +--- Sets the current working directory with the string `cwd`. +--- @param cwd string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.chdir(cwd) end + +--- Returns the title of the current process. +--- @return string? title +--- @return string? err +--- @return uv.error_name? err_name +function uv.get_process_title() end + +--- Sets the title of the current process with the string `title`. +--- @param title string +--- @return 0? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.set_process_title(title) end + +--- Returns the current total system memory in bytes. +--- @return number +function uv.get_total_memory() end + +--- Returns the current free system memory in bytes. +--- @return number +function uv.get_free_memory() end + +--- Gets the amount of memory available to the process in bytes based on limits +--- imposed by the OS. If there is no such constraint, or the constraint is unknown, +--- 0 is returned. Note that it is not unusual for this value to be less than or +--- greater than the total system memory. +--- @return number +function uv.get_constrained_memory() end + +--- Gets the amount of free memory that is still available to the process (in +--- bytes). This differs from `uv.get_free_memory()` in that it takes into account +--- any limits imposed by the OS. If there is no such constraint, or the constraint +--- is unknown, the amount returned will be identical to `uv.get_free_memory()`. +--- @return number +function uv.get_available_memory() end + +--- Returns the resident set size (RSS) for the current process. +--- @return integer? rss +--- @return string? err +--- @return uv.error_name? err_name +function uv.resident_set_memory() end + +--- @class uv.getrusage.result +--- +--- (user CPU time used) +--- @field utime uv.getrusage.result.time +--- +--- (system CPU time used) +--- @field stime uv.getrusage.result.time +--- +--- (maximum resident set size) +--- @field maxrss integer +--- +--- (integral shared memory size) +--- @field ixrss integer +--- +--- (integral unshared data size) +--- @field idrss integer +--- +--- (integral unshared stack size) +--- @field isrss integer +--- +--- (page reclaims (soft page faults)) +--- @field minflt integer +--- +--- (page faults (hard page faults)) +--- @field majflt integer +--- +--- (swaps) +--- @field nswap integer +--- +--- (block input operations) +--- @field inblock integer +--- +--- (block output operations) +--- @field oublock integer +--- +--- (IPC messages sent) +--- @field msgsnd integer +--- +--- (IPC messages received) +--- @field msgrcv integer +--- +--- (signals received) +--- @field nsignals integer +--- +--- (voluntary context switches) +--- @field nvcsw integer +--- +--- (involuntary context switches) +--- @field nivcsw integer + +--- @class uv.getrusage.result.time +--- @field sec integer +--- @field usec integer + +--- Returns the resource usage. +--- @return uv.getrusage.result? rusage +--- @return string? err +--- @return uv.error_name? err_name +function uv.getrusage() end + +--- Gets the resource usage measures for the calling thread. +--- +--- **Note** Not supported on all platforms. May return `ENOTSUP`. +--- On macOS and Windows not all fields are set (the unsupported fields are filled +--- with zeroes). +--- @return uv.getrusage.result? rusage +--- @return string? err +--- @return uv.error_name? err_name +function uv.getrusage_thread() end + +--- Returns an estimate of the default amount of parallelism a program should use. Always returns a non-zero value. +--- +--- On Linux, inspects the calling thread’s CPU affinity mask to determine if it has been pinned to specific CPUs. +--- +--- On Windows, the available parallelism may be underreported on systems with more than 64 logical CPUs. +--- +--- On other platforms, reports the number of CPUs that the operating system considers to be online. +--- @return integer +function uv.available_parallelism() end + +--- @class uv.cpu_info.cpu_info +--- @field model string +--- @field speed integer +--- @field times uv.cpu_info.cpu_info.times + +--- @class uv.cpu_info.cpu_info.times +--- @field user integer +--- @field nice integer +--- @field sys integer +--- @field idle integer +--- @field irq integer + +--- Returns information about the CPU(s) on the system as a table of tables for each +--- CPU found. +--- @return table? cpu_info +--- @return string? err +--- @return uv.error_name? err_name +function uv.cpu_info() end + +--- Returns the maximum size of the mask used for process/thread affinities, or +--- `ENOTSUP` if affinities are not supported on the current platform. +--- @return integer? size +--- @return string? err +--- @return uv.error_name? err_name +function uv.cpumask_size() end + +--- @deprecated Please use `uv.os_getpid()` instead. +--- @return integer +function uv.getpid() end + +--- Returns the user ID of the process. +--- **Note**: +--- This is not a libuv function and is not supported on Windows. +--- @return integer +function uv.getuid() end + +--- Returns the group ID of the process. +--- **Note**: +--- This is not a libuv function and is not supported on Windows. +--- @return integer +function uv.getgid() end + +--- Sets the user ID of the process with the integer `id`. +--- **Note**: +--- This is not a libuv function and is not supported on Windows. +--- @param id integer +function uv.setuid(id) end + +--- Sets the group ID of the process with the integer `id`. +--- **Note**: +--- This is not a libuv function and is not supported on Windows. +--- @param id integer +function uv.setgid(id) end + +--- Returns a current high-resolution time in nanoseconds as a number. This is +--- relative to an arbitrary time in the past. It is not related to the time of day +--- and therefore not subject to clock drift. The primary use is for measuring +--- time between intervals. +--- @return number +function uv.hrtime() end + +--- Obtain the current system time from a high-resolution real-time or monotonic +--- clock source. `clock_id` can be the string `"monotonic"` or `"realtime"`. +--- +--- The real-time clock counts from the UNIX epoch (1970-01-01) and is subject +--- to time adjustments; it can jump back in time. +--- +--- The monotonic clock counts from an arbitrary point in the past and never +--- jumps back in time. +--- @param clock_id string +--- @return { sec: integer, nsec: integer }? time +--- @return string? err +--- @return uv.error_name? err_name +function uv.clock_gettime(clock_id) end + +--- Returns the current system uptime in seconds. +--- @return number? uptime +--- @return string? err +--- @return uv.error_name? err_name +function uv.uptime() end + +--- Prints all handles associated with the main loop to stderr. The format is +--- `[flags] handle-type handle-address`. Flags are `R` for referenced, `A` for +--- active and `I` for internal. +--- **Note**: +--- This is not available on Windows. +--- **Warning**: +--- This function is meant for ad hoc debugging, there are no API/ABI +--- stability guarantees. +function uv.print_all_handles() end + +--- The same as `uv.print_all_handles()` except only active handles are printed. +--- **Note**: +--- This is not available on Windows. +--- **Warning**: +--- This function is meant for ad hoc debugging, there are no API/ABI +--- stability guarantees. +function uv.print_active_handles() end + +--- Used to detect what type of stream should be used with a given file +--- descriptor `fd`. Usually this will be used during initialization to guess the +--- type of the stdio streams. +--- @param fd integer +--- @return string +function uv.guess_handle(fd) end + +--- Cross-platform implementation of `gettimeofday(2)`. Returns the seconds and +--- microseconds of a unix time as a pair. +--- @return integer? seconds +--- @return integer|string microseconds_or_err +--- @return uv.error_name? err_name +function uv.gettimeofday() end + +--- @class uv.interface_addresses.addresses +--- @field ip string +--- @field family string +--- @field netmask string +--- @field internal boolean +--- @field mac string + +--- Returns address information about the network interfaces on the system in a +--- table. Each table key is the name of the interface while each associated value +--- is an array of address information where fields are `ip`, `family`, `netmask`, +--- `internal`, and `mac`. +--- +--- See [Constants][] for supported address `family` output values. +--- @return table addresses +function uv.interface_addresses() end + +--- IPv6-capable implementation of `if_indextoname(3)`. +--- @param ifindex integer +--- @return string? name +--- @return string? err +--- @return uv.error_name? err_name +function uv.if_indextoname(ifindex) end + +--- Retrieves a network interface identifier suitable for use in an IPv6 scoped +--- address. On Windows, returns the numeric `ifindex` as a string. On all other +--- platforms, `uv.if_indextoname()` is used. +--- @param ifindex integer +--- @return string? iid +--- @return string? err +--- @return uv.error_name? err_name +function uv.if_indextoiid(ifindex) end + +--- Returns the load average as a triad. Not supported on Windows. +--- @return number, number, number +function uv.loadavg() end + +--- @class uv.os_uname.info +--- @field sysname string +--- @field release string +--- @field version string +--- @field machine string + +--- Returns system information. +--- @return uv.os_uname.info info +function uv.os_uname() end + +--- Returns the hostname. +--- @return string +function uv.os_gethostname() end + +--- Returns the environment variable specified by `name` as string. The internal +--- buffer size can be set by defining `size`. If omitted, `LUAL_BUFFERSIZE` is +--- used. If the environment variable exceeds the storage available in the internal +--- buffer, `ENOBUFS` is returned. If no matching environment variable exists, +--- `ENOENT` is returned. +--- **Warning**: +--- This function is not thread-safe. +--- @param name string +--- @param size integer? +--- @return string? value +--- @return string? err +--- @return uv.error_name? err_name +function uv.os_getenv(name, size) end + +--- Sets the environmental variable specified by `name` with the string `value`. +--- **Warning**: +--- This function is not thread-safe. +--- @param name string +--- @param value string +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.os_setenv(name, value) end + +--- Unsets the environmental variable specified by `name`. +--- **Warning**: +--- This function is not thread-safe. +--- @param name string +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.os_unsetenv(name) end + +--- Returns all environmental variables as a dynamic table of names associated with +--- their corresponding values. +--- **Warning**: +--- This function is not thread-safe. +--- @return table +function uv.os_environ() end + +--- Returns the home directory. +--- **Warning**: +--- This function is not thread-safe. +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv.os_homedir() end + +--- Returns a temporary directory. +--- **Warning**: +--- This function is not thread-safe. +--- @return string? path +--- @return string? err +--- @return uv.error_name? err_name +function uv.os_tmpdir() end + +--- @class uv.os_get_passwd.passwd +--- @field username string +--- @field uid integer +--- @field gid integer +--- @field shell string +--- @field homedir string + +--- Returns password file information. +--- @return uv.os_get_passwd.passwd passwd +function uv.os_get_passwd() end + +--- Returns the current process ID. +--- @return number +function uv.os_getpid() end + +--- Returns the parent process ID. +--- @return number +function uv.os_getppid() end + +--- Returns the scheduling priority of the process specified by `pid`. +--- @param pid integer +--- @return integer? priority +--- @return string? err +--- @return uv.error_name? err_name +function uv.os_getpriority(pid) end + +--- Sets the scheduling priority of the process specified by `pid`. The `priority` +--- range is between -20 (high priority) and 19 (low priority). +--- @param pid integer +--- @param priority integer +--- @return boolean? success +--- @return string? err +--- @return uv.error_name? err_name +function uv.os_setpriority(pid, priority) end + +--- Fills a string of length `len` with cryptographically strong random bytes +--- acquired from the system CSPRNG. `flags` is reserved for future extension +--- and must currently be `nil` or `0` or `{}`. +--- +--- Short reads are not possible. When less than `len` random bytes are available, +--- a non-zero error value is returned or passed to the callback. If the callback +--- is omitted, this function is completed synchronously. +--- +--- The synchronous version may block indefinitely when not enough entropy is +--- available. The asynchronous version may not ever finish when the system is +--- low on entropy. +--- @param len integer +--- @param flags 0|{}? +--- @return string? bytes +--- @return string? err +--- @return uv.error_name? err_name +--- @overload fun(len: integer, flags: 0|{}?, callback: fun(err: string?, bytes: string?)): 0?, string?, uv.error_name? +function uv.random(len, flags) end + +--- Returns the libuv error message and error name (both in string form, see [`err` and `name` in Error Handling](#error-handling)) equivalent to the given platform dependent error code: POSIX error codes on Unix (the ones stored in errno), and Win32 error codes on Windows (those returned by GetLastError() or WSAGetLastError()). +--- @param errcode integer +--- @return string? message +--- @return string? name +function uv.translate_sys_error(errcode) end + + +--- # Metrics operations + +--- Retrieve the amount of time the event loop has been idle in the kernel’s event +--- provider (e.g. `epoll_wait`). The call is thread safe. +--- +--- The return value is the accumulated time spent idle in the kernel’s event +--- provider starting from when the [`uv_loop_t`][] was configured to collect the idle time. +--- +--- **Note:** The event loop will not begin accumulating the event provider’s idle +--- time until calling `loop_configure` with `"metrics_idle_time"`. +--- @return number +function uv.metrics_idle_time() end + +--- @class uv.metrics_info.info +--- @field loop_count number +--- @field events integer +--- @field events_waiting number + +--- Get the metrics table from current set of event loop metrics. It is recommended +--- to retrieve these metrics in a `prepare` callback (see `uv.new_prepare`, +--- `uv.prepare_start`) in order to make sure there are no inconsistencies with the +--- metrics counters. +--- @return uv.metrics_info.info info +function uv.metrics_info() end + + +--- # String manipulation functions +--- +--- These string utilities are needed internally for dealing with Windows, and are exported to allow clients to work uniformly with this data when the libuv API is not complete. +--- +--- **Notes**: +--- +--- 1. New in luv version 1.49.0. +--- 2. See [the WTF-8 spec](https://simonsapin.github.io/wtf-8/) for information about WTF-8. +--- 3. Luv uses Lua-style strings, which means that all inputs and return values (UTF-8 or UTF-16 strings) do not include a NUL terminator. + +--- Get the length (in bytes) of a UTF-16 (or UCS-2) string `utf16` value after converting it to WTF-8. +--- @param utf16 string +--- @return integer +function uv.utf16_length_as_wtf8(utf16) end + +--- Convert UTF-16 (or UCS-2) string `utf16` to WTF-8 string. The endianness of the UTF-16 (or UCS-2) string is assumed to be the same as the native endianness of the platform. +--- @param utf16 string +--- @return string +function uv.utf16_to_wtf8(utf16) end + +--- Get the length (in UTF-16 code units) of a WTF-8 `wtf8` value after converting it to UTF-16 (or UCS-2). Note: The number of bytes needed for a UTF-16 (or UCS-2) string is ` * 2`. +--- @param wtf8 string +--- @return integer +function uv.wtf8_length_as_utf16(wtf8) end + +--- Convert WTF-8 string in `wtf8` to UTF-16 (or UCS-2) string. The endianness of the UTF-16 (or UCS-2) string will be the same as the native endianness of the platform. +--- @param wtf8 string +--- @return string +function uv.wtf8_to_utf16(wtf8) end + + +--- --- +--- +--- [luv]: https://github.com/luvit/luv +--- [luvit]: https://github.com/luvit/luvit +--- [libuv]: https://github.com/libuv/libuv +--- [libuv documentation page]: http://docs.libuv.org/ +--- [libuv API documentation]: http://docs.libuv.org/en/v1.x/api.html +--- [error constants]: https://docs.libuv.org/en/v1.x/errors.html#error-constants + + +--- @class uv.address +--- @field addr string +--- @field family string +--- @field port integer? +--- @field socktype string +--- @field protocol string +--- @field canonname string? + +--- @alias uv.buffer +--- | string +--- | string[] + +--- @class uv.socketinfo +--- @field ip string +--- @field family string +--- @field port integer + +--- @alias uv.threadargs +--- | number +--- | boolean +--- | string +--- | userdata + +--- @class uv.uv_connect_t : uv.uv_req_t + +--- @class uv.uv_fs_t : uv.uv_req_t + +--- @class uv.uv_getaddrinfo_t : uv.uv_req_t + +--- @class uv.uv_getnameinfo_t : uv.uv_req_t + +--- @class uv.uv_shutdown_t : uv.uv_req_t + +--- @class uv.uv_udp_send_t : uv.uv_req_t + +--- @class uv.uv_work_t : uv.uv_req_t + +--- @class uv.uv_write_t : uv.uv_req_t +