---@meta ffi

--------------------------------------------------------------------------------
-- cffi-lua FFI 模块
--------------------------------------------------------------------------------

---@alias ffi_ct string|ffi_ctype|ffi_cdata
---@alias ffi_finalizer any
---@alias ffi_cdef_param any
---@alias ffi_abi_param
---| '32bit'
---| '64bit'
---| 'be'
---| 'le'
---| 'win'
---| 'eabi'
---| 'uwp'
---| 'elfv2'
---| 'unionval'
---| 'fpu'
---| 'hardfp'
---| 'softfp'
---| string
---@alias ffi_os_name
---| 'Windows'
---| 'Linux'
---| 'OSX'
---| 'BSD'
---| 'POSIX'
---| 'Other'
---| string
---@alias ffi_arch_name
---| 'alpha'
---| 'arm'
---| 'armeb'
---| 'arm64'
---| 'arm64be'
---| 'hppa'
---| 'm68k'
---| 'microblaze'
---| 'microblazeel'
---| 'mips'
---| 'mipsel'
---| 'mips32r6'
---| 'mips32r6el'
---| 'mips64'
---| 'mips64el'
---| 'mips64r6'
---| 'mips64r6el'
---| 'or1k'
---| 'ppc'
---| 'ppcle'
---| 'ppc64le'
---| 'ppc64'
---| 'riscv32'
---| 'riscv64'
---| 's390'
---| 's390x'
---| 'sh4'
---| 'sh4eb'
---| 'sparc'
---| 'sparc64'
---| 'x64'
---| 'x86'
---| 'unknown'
---| string

---@class ffi_clib*
---@field [string] any 动态 C 符号
local clib = {}

---@class ffi_ctype*
---@operator call(...): ffi_cdata
local ctype = {}

---@class ffi_cdata*
---@field [integer] any 指针、引用、数组或聚合类型索引
---@field [string] any 聚合字段或动态成员
---@operator add(any): ffi_cdata
---@operator sub(any): ffi_cdata|integer
---@operator mul(any): ffi_cdata
---@operator div(any): ffi_cdata
---@operator mod(any): ffi_cdata
---@operator pow(any): ffi_cdata
---@operator unm: ffi_cdata
---@operator len: integer
---@operator concat(any): string
---@operator eq(any): boolean
---@operator lt(any): boolean
---@operator le(any): boolean
local cdata = {}

--- 释放 callback 资源。
---
--- 仅 callback cdata 支持该方法。
function cdata:free() end

--- 为 callback 绑定新的 Lua 函数。
---
--- 仅 callback cdata 支持该方法。
---@param func function 新 callback 函数
function cdata:set(func) end

---@class ffi_metatype*
---@field __add? fun(a:any, b:any):any
---@field __sub? fun(a:any, b:any):any
---@field __mul? fun(a:any, b:any):any
---@field __div? fun(a:any, b:any):any
---@field __mod? fun(a:any, b:any):any
---@field __pow? fun(a:any, b:any):any
---@field __unm? fun(a:any):any
---@field __concat? fun(a:any, b:any):any
---@field __len? fun(a:any):integer
---@field __eq? fun(a:any, b:any):boolean
---@field __lt? fun(a:any, b:any):boolean
---@field __le? fun(a:any, b:any):boolean
---@field __index? table|fun(self:any, key:any):any
---@field __newindex? table|fun(self:any, key:any, value:any)
---@field __call? fun(self:any, ...:any):any
---@field __new? fun(ct:ffi_ctype, ...:any):any
---@field __gc? fun(self:any)
---@field __tostring? fun(self:any):string
---@field __pairs? fun(self:any):function, any, any
---@field __ipairs? fun(self:any):function, any, any
---@field __idiv? fun(a:any, b:any):any
---@field __band? fun(a:any, b:any):any
---@field __bor? fun(a:any, b:any):any
---@field __bxor? fun(a:any, b:any):any
---@field __bnot? fun(a:any):any
---@field __shl? fun(a:any, b:any):any
---@field __shr? fun(a:any, b:any):any
---@field __name? string
---@field __close? fun(self:any, err:any)

---@class ffi*
---@field C ffi_clib 默认 C 符号命名空间
---@field os ffi_os_name 目标 OS 名称
---@field arch ffi_arch_name 目标架构名称
---@field nullptr ffi_cdata 空指针常量 `(void *)0`
---@type ffi*
local M = {}

M.C = clib
M.os = "OSX"
M.arch = "arm64"
M.nullptr = cdata

--- 声明 C 类型、常量或函数。
---
--- 支持参数化类型，额外参数会传给声明解析器。
---@param def string C 声明文本
---@param ... ffi_cdef_param 参数化声明参数
function M.cdef(def, ...) end

--- 加载动态库并返回符号命名空间。
---@param name string 动态库名称或路径
---@param global? boolean 是否以全局方式加载
---@return ffi_clib clib C 符号命名空间
function M.load(name, global) end

--- 创建 C 数据对象。
---@param ct ffi_ct C 类型
---@param ... any 初始化参数；VLA/VLS 类型需要先传元素数量
---@return ffi_cdata cdata C 数据对象
function M.new(ct, ...) end

--- 按 C cast 规则创建 C 数据对象。
---@param ct ffi_ct C 类型
---@param init any 初始值
---@return ffi_cdata cdata C 数据对象
function M.cast(ct, init) end

--- 创建 C 类型对象。
---@param ct ffi_ct C 类型
---@param ... ffi_cdef_param 参数化类型参数
---@return ffi_ctype ctype C 类型对象
function M.typeof(ct, ...) end

--- 为 struct/union 类型设置 metatable 并返回对应 ctype。
---@param ct ffi_ct struct 或 union 类型
---@param metatable ffi_metatype metatable
---@return ffi_ctype ctype C 类型对象
function M.metatype(ct, metatable) end

--- 返回 cdata 的地址。
---@param cdata ffi_cdata C 数据对象
---@return ffi_cdata ptr 指针 cdata
function M.addressof(cdata) end

--- 给 cdata 设置或清除 GC finalizer。
---
--- 传入 nil 会清除已有 finalizer。
---@param cdata ffi_cdata C 数据对象
---@param finalizer ffi_finalizer|nil finalizer
---@return ffi_cdata cdata 原 cdata
function M.gc(cdata, finalizer) end

--- 返回 C 类型或 cdata 的字节大小。
---@param ct ffi_ct C 类型或 cdata
---@param nelem? integer VLA/VLS 元素数量
---@return integer? size 字节大小；未知时为 nil
function M.sizeof(ct, nelem) end

--- 返回 C 类型的最小对齐。
---@param ct ffi_ct C 类型
---@return integer align 对齐字节数
function M.alignof(ct) end

--- 返回聚合类型字段偏移。
---@param ct ffi_ct struct 或 union 类型
---@param field string 字段名
---@return integer? offset 字节偏移；字段不存在时为 nil
function M.offsetof(ct, field) end

--- 判断对象是否为指定 C 类型。
---@param ct ffi_ct C 类型
---@param obj any 待检查对象
---@return boolean ok 是否匹配
function M.istype(ct, obj) end

--- 获取当前 errno，并可设置新的 errno。
---@param newerr? integer 新 errno
---@return integer err 调用前的 errno
function M.errno(newerr) end

--- 从 C 字符串或内存区域创建 Lua 字符串。
---@overload fun(str:string):string
---@overload fun(str:string, len:integer):string
---@param ptr ffi_cdata C 字符串指针、数组或 cdata
---@param len? integer 字节长度；省略时按零结尾字符串处理
---@return string str Lua 字符串
function M.string(ptr, len) end

--- 复制内存。
---@overload fun(dst:ffi_cdata|userdata, src:string)
---@overload fun(dst:ffi_cdata|userdata, src:string, len:integer)
---@param dst ffi_cdata|userdata 目标指针
---@param src ffi_cdata|userdata 源指针
---@param len integer 字节长度
function M.copy(dst, src, len) end

--- 填充内存。
---@param dst ffi_cdata|userdata 目标指针
---@param len integer 字节长度
---@param c? integer 填充值，默认 0
function M.fill(dst, len, c) end

--- 按 C 函数返回值规则将 cdata 转成 Lua 值或 cdata。
---@param cdata ffi_cdata C 数据对象
---@return any value 转换后的值
function M.toretval(cdata) end

--- 解析 C 常量表达式并返回 cdata。
---@param expr string C 常量表达式
---@return ffi_cdata value C 数据对象
function M.eval(expr) end

--- 判断目标 ABI 是否满足参数。
---@param param ffi_abi_param ABI 参数
---@return boolean ok 是否满足
function M.abi(param) end

--- 将 cdata 或普通 Lua 值转换为 Lua number。
---@param value any 待转换值
---@param base? integer 进制；非 cdata 时透传给 Lua `tonumber`
---@return number? n 数字；无法转换时为 nil
function M.tonumber(value, base) end

--- 类似 Lua `type`，但 cvalue 返回 `"cdata"`。
---@param value any 待检查值
---@return string type 类型名
function M.type(value) end

return M
