Skip to content

Commit

Permalink
Runtime: Add a function to more easily unpack VFS assets
Browse files Browse the repository at this point in the history
It's handy for non-executable files, such as shader programs (my use case) or shared libraries which need to be FFI-loaded. The latter should ideally be loaded from the VFS directly, but that's still a bit off in the future. This is a first step in the general direction, however.
  • Loading branch information
rdw-software committed Aug 21, 2024
1 parent 6c5c929 commit 1d899ae
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 0 deletions.
15 changes: 15 additions & 0 deletions Runtime/Libraries/vfs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ function vfs.dofile(zipApp, filePath)
return nil, "Failed to load file " .. filePath .. " (no such entry exists)"
end

function vfs.extract(zipApp, filePath)
validation.validateTable(zipApp, "zipApp")
validation.validateString(filePath, "filePath")

local reader = zipApp.reader
for index = 1, reader:get_num_files() do
if reader:get_filename(index) == filePath then
local fileContents = reader:extract(index)
return fileContents
end
end

return nil, "Failed to extract file " .. filePath .. " (no such entry exists)"
end

-- VFS searcher: Allow require to find files stored in the VFS of LUAZIP apps
-- See https://www.lua.org/manual/5.2/manual.html#pdf-package.searchers
function vfs.searcher(zipApp, moduleName)
Expand Down
35 changes: 35 additions & 0 deletions Tests/BDD/vfs-library.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,39 @@ describe("vfs", function()
assertEquals(vfs.dofile(zipApp, path.win32.join("subdirectory", "another-file.lua")), 42)
end)
end)

describe("extract", function()
local fileContents = C_FileSystem.ReadFile(path.join("Tests", "Fixtures", "hello-world-app.bin"))
local zipApp = assert(vfs.decode(fileContents))

it("should throw if an invalid zip app was passed", function()
assertThrows(function()
vfs.extract(nil, nil)
end, "Expected argument zipApp to be a table value, but received a nil value instead")
end)

it("should throw if an invalid file path was passed", function()
assertThrows(function()
vfs.extract(zipApp, nil)
end, "Expected argument filePath to be a string value, but received a nil value instead")
end)

it("should throw if the given file doesn't exist within the archive", function()
assertFailure(function()
return vfs.extract(zipApp, "this-file-does-not-exist")
end, "Failed to extract file this-file-does-not-exist (no such entry exists)")
end)

it("should return the decompressed file contents", function()
local filePath = path.join("Tests", "Fixtures", "hello-world-app", "subdirectory", "another-file.lua")
local expectedFileContents = C_FileSystem.ReadFile(filePath)

-- The fixture was apparently generated with different formatter settings - whatever
expectedFileContents = expectedFileContents:gsub("\n", "")
expectedFileContents = expectedFileContents:gsub("\r", "")

local vfsPath = path.win32.join("subdirectory", "another-file.lua")
assertEquals(vfs.extract(zipApp, vfsPath), expectedFileContents)
end)
end)
end)

0 comments on commit 1d899ae

Please sign in to comment.