This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Nov 20, 2020. It is now read-only.

Repository files navigation

$Id$
PLUTO - Heavy duty persistence for Lua
Pluto is a library which allows users to write arbitrarily large portions
of the "Lua universe" into a flat file, and later read them back into the
same or a different Lua universe. Object references are appropriately
handled, such that the file contains everything needed to recreate the
objects in question.
Pluto has the following major features: * Can persist any Lua function
* Can persist threads * Works with any Lua chunkreader/chunkwriter * Support for "invariant" permanent objects, of all datatypes
* Can invoke metafunctions for custom persistence of tables and userdata
Pluto 2.2 requires Lua 5.1.3. If you need to use Pluto with Lua
5.0, please use version 1.2 of Pluto.
Starting with version 2.2, Pluto no longer depends on the Lua sources.
Instead, it subsumes the required headers into its own codebase.
As a result, it may not work properly with Lua version 5.1.4 or later.
Pluto may have bugs. Users are advised to define lua_assert in luaconf.h to something useful when compiling in debug mode, to catch
assertions by Pluto and Lua.
The Pluto library consists of two public functions.
int pluto_persist(lua_State *L, lua_Chunkwriter writer, void *ud)
This function recursively persists the Lua object in stack position 2
and all other objects which are directly or indirectly referenced by
it, except those referenced in the permanent object table. The data
is written using the chunk-writer given, and that writer is passed
the arbitrary pointer value ud.
The Lua stack must contain exactly and only these two items, in order:
1. A table of permanent objects, that should not be persisted. For each
permanent object, the object itself should be the key, and a unique
object of any type should be the value. Likely candidates for this table include Lua functions (including those in the Lua libraries) that are loaded at load-time. It must include all non-persistable objects that are referenced by the object to be persisted. The table is not modified by the function. Objects in this table are considered "opaque" and are not examined or descended into. Objects should not appear in the table multiple times; the result of doing this is undefined (though probably harmless). NOTE: If you are planning to persist threads, keep in mind that all yielded threads have coroutine.yield on the tops of their stacks. Since it's a C function, it should be put here. For complex permanents, it may be a good idea to use the __index meta-function of the permanents table to "search" for permanents.
2. The single object to be persisted. In many cases, this will be the
global table. For more flexibility, however, it may be something like a
table built for the occasion, with various values to keep track of. The
object may not be nil.
int pluto_unpersist(lua_State *L, lua_Chunkreader reader, void *ud)
This function loads in a Lua object and places it on top of the stack. All
objects directly or indirectly referenced by it are also loaded.
The Lua stack must contain, as its top value, a table of permanent
objects. This table should be like the permanent object table used when
persisting, but with the key and value of each pair reversed. These objects are used as substitutes for those referenced in their positions when persisting, and under most circumstances should be identical objects
to those referenced in the permanents table used for persisting. It's okay for multiple keys to refer to the same object.
RUNNING PLUTO FROM LUA:
It is also possible to invoke pluto from a Lua script. The C function
pluto_open() will register pluto.persist and pluto.unpersist, lua functions
which operate on strings. The first takes a permanents table and a root object, and returns a string; the second takes a permanents table and a string, and returns the root object.
An error will be raised if pluto.persist is called from a thread which is
itself referenced by the root object.
SPECIAL PERSISTENCE:
Tables and userdata have special persistence semantics. These semantics are
keyed to the value of the object's metatable's __persist member, if any. This
member may be any of the following four values:
1. Boolean "true": The table or userdata is persisted literally; tables are
persisted member-by-member, and userdata are written out as literal data.
2. Boolean "false": An error is returned, indicating that the object cannot
be persisted.
3. A function: This function should take one argument, the object in question,
and return one result, a closure. This "fixup closure", in turn, will be persisted, and during unpersistence will be called. The closure will be responsible for recreating the object with the appropriate data, based on its upvalues.
4. Nil, or no metatable. In the case of tables, the table is literally
persisted. In the case of userdata, an error is returned.
Here's an example of special persistence for a simple 3d vector object:
vec = { x = 2, y = 1, z = 4 }
setmetatable(vec, { __persist = function(oldtbl)
local x = oldtbl.x
local y = oldtbl.y
local z = oldtbl.z
local mt = getmetatable(oldtbl)
return function()
newtbl = {}
newtbl.x = x
newtbl.y = y
newtbl.z = z
setmetatable(newtbl, mt)
return newtbl
end
end })
Note how x, y, z, and the mt are explicitly pulled out of the table. It is important that the fixup closure returned not reference the original table directly, as that table would again be persisted as an upvalue, leading to an infinite loop. Also note that the object's metatable is NOT automatically persisted; it is necessary for the fixup closure to reset it, if it wants.
LIMITATIONS/TODO: * Light userdata are persisted literally, as their pointer values. This may or may not be what you want. * Closures of C functions may not be persisted. Once it becomes possible
to specify a C function "proto" as a permanent object, this restriction
will be relaxed.
BUGS: None known. Emphasis on the 'known'.

About

Heavy duty persistence for Lua

Resources

Stars

2 stars

Watchers

5 watching

Forks

Releases

Packages

Contributors

Languages