refactor(loader): simplify Loader.write/read

This commit is contained in:
Lewis Russell
2024-10-31 14:18:51 +00:00
parent f8fc6cb157
commit 53536be62a

View File

@@ -126,18 +126,19 @@ end
--- Saves the cache entry for a given module or file --- Saves the cache entry for a given module or file
---@param cname string cache filename ---@param cname string cache filename
---@param entry CacheEntry ---@param hash CacheHash
---@param chunk function
---@private ---@private
function Loader.write(cname, entry) function Loader.write(cname, hash, chunk)
local f = assert(uv.fs_open(cname, 'w', 438)) local f = assert(uv.fs_open(cname, 'w', 438))
local header = { local header = {
Loader.VERSION, Loader.VERSION,
entry.hash.size, hash.size,
entry.hash.mtime.sec, hash.mtime.sec,
entry.hash.mtime.nsec, hash.mtime.nsec,
} }
uv.fs_write(f, table.concat(header, ',') .. '\0') uv.fs_write(f, table.concat(header, ',') .. '\0')
uv.fs_write(f, entry.chunk) uv.fs_write(f, string.dump(chunk))
uv.fs_close(f) uv.fs_close(f)
end end
@@ -156,29 +157,34 @@ end
--- Loads the cache entry for a given module or file --- Loads the cache entry for a given module or file
---@param cname string cache filename ---@param cname string cache filename
---@return CacheEntry? ---@return CacheHash? hash
---@return string? chunk
---@private ---@private
function Loader.read(cname) function Loader.read(cname)
local data = readfile(cname, 438) local data = readfile(cname, 438)
if data then if not data then
local zero = data:find('\0', 1, true) return
if not zero then
return
end
---@type integer[]|{[0]:integer}
local header = vim.split(data:sub(1, zero - 1), ',')
if tonumber(header[1]) ~= Loader.VERSION then
return
end
return {
hash = {
size = tonumber(header[2]),
mtime = { sec = tonumber(header[3]), nsec = tonumber(header[4]) },
},
chunk = data:sub(zero + 1),
}
end end
local zero = data:find('\0', 1, true)
if not zero then
return
end
---@type integer[]|{[0]:integer}
local header = vim.split(data:sub(1, zero - 1), ',')
if tonumber(header[1]) ~= Loader.VERSION then
return
end
local hash = {
size = tonumber(header[2]),
mtime = { sec = tonumber(header[3]), nsec = tonumber(header[4]) },
}
local chunk = data:sub(zero + 1)
return hash, chunk
end end
--- The `package.loaders` loader for Lua files using the cache. --- The `package.loaders` loader for Lua files using the cache.
@@ -236,15 +242,15 @@ end
--- * file size --- * file size
--- * mtime in seconds --- * mtime in seconds
--- * mtime in nanoseconds --- * mtime in nanoseconds
---@param h1 CacheHash ---@param a? CacheHash
---@param h2 CacheHash ---@param b? CacheHash
---@private ---@private
function Loader.eq(h1, h2) function Loader.eq(a, b)
return h1 return a
and h2 and b
and h1.size == h2.size and a.size == b.size
and h1.mtime.sec == h2.mtime.sec and a.mtime.sec == b.mtime.sec
and h1.mtime.nsec == h2.mtime.nsec and a.mtime.nsec == b.mtime.nsec
end end
--- Loads the given module path using the cache --- Loads the given module path using the cache
@@ -258,9 +264,6 @@ end
function Loader.load(modpath, opts) function Loader.load(modpath, opts)
opts = opts or {} opts = opts or {}
local hash = Loader.get_hash(modpath) local hash = Loader.get_hash(modpath)
---@type function?, string?
local chunk, err
if not hash then if not hash then
-- trigger correct error -- trigger correct error
return Loader._loadfile(modpath, opts.mode, opts.env) return Loader._loadfile(modpath, opts.mode, opts.env)
@@ -268,20 +271,18 @@ function Loader.load(modpath, opts)
local cname = Loader.cache_file(modpath) local cname = Loader.cache_file(modpath)
local entry = Loader.read(cname) local e_hash, e_chunk = Loader.read(cname)
if entry and Loader.eq(entry.hash, hash) then if Loader.eq(e_hash, hash) and e_chunk then
-- found in cache and up to date -- found in cache and up to date
chunk, err = load(entry.chunk --[[@as string]], '@' .. modpath, opts.mode, opts.env) local chunk, err = load(e_chunk, '@' .. modpath, opts.mode, opts.env)
if not (err and err:find('cannot load incompatible bytecode', 1, true)) then if not (err and err:find('cannot load incompatible bytecode', 1, true)) then
return chunk, err return chunk, err
end end
end end
entry = { hash = hash, modpath = modpath }
chunk, err = Loader._loadfile(modpath, opts.mode, opts.env) local chunk, err = Loader._loadfile(modpath, opts.mode, opts.env)
if chunk then if chunk then
entry.chunk = string.dump(chunk) Loader.write(cname, hash, chunk)
Loader.write(cname, entry)
end end
return chunk, err return chunk, err
end end