mirror of
https://github.com/pkulchenko/serpent.git
synced 2024-11-21 23:24:24 +00:00
Added load
function to deserialize; updated documentation (closes #9).
This commit is contained in:
parent
b290a5d522
commit
4e4a19df1d
14
README.md
14
README.md
@ -37,6 +37,10 @@ print(serpent.block(a)) -- multi-line indented, no self-ref section
|
||||
local fun, err = loadstring(serpent.dump(a))
|
||||
if err then error(err) end
|
||||
local copy = fun()
|
||||
|
||||
-- or using serpent.load:
|
||||
local ok, copy = serpent.load(serpent.dump(a))
|
||||
print(ok and copy[3] == a[3])
|
||||
```
|
||||
|
||||
## Functions
|
||||
@ -51,6 +55,12 @@ internal function, but set different options by default:
|
||||
Note that `line` and `block` functions return pretty-printed data structures and if you want to deserialize them, you need to add `return` before running them through `loadstring`.
|
||||
For example: `loadstring('return '..require('mobdebug').line("foo"))() == "foo"`.
|
||||
|
||||
While you can use `loadstring` or `load` functions to load serialized fragments, Serpent also provides `load` function that adds safety checks and reports an error if there is any executable code in the fragment.
|
||||
|
||||
* `ok, res = load(str[, {safe = true}])` -- loads serialized fragment; you need to pass `{safe = false}` as the second value if you want to turn safety checks off.
|
||||
|
||||
Similar to `pcall` and `loadstring` calls, `load` returns status as the first value and the result or the error message as the second value.
|
||||
|
||||
## Options
|
||||
|
||||
* indent (string) -- indentation; triggers long multi-line output
|
||||
@ -167,6 +177,10 @@ See LICENSE file.
|
||||
|
||||
## History
|
||||
|
||||
### v0.26 (Nov 05 2013)
|
||||
- Added `load` function that (safely) loads serialized/pretty-printed values.
|
||||
- Updated documentation.
|
||||
|
||||
### v0.25 (Sep 29 2013)
|
||||
- Added `maxnum` option to limit the number of elements in tables.
|
||||
- Optimized processing of tables with numeric indexes.
|
||||
|
25
misc/serpent-0.26-1.rockspec
Normal file
25
misc/serpent-0.26-1.rockspec
Normal file
@ -0,0 +1,25 @@
|
||||
package = "serpent"
|
||||
version = "0.26-1"
|
||||
source = {
|
||||
url = "git://github.com/pkulchenko/serpent.git",
|
||||
tag = "0.26"
|
||||
}
|
||||
|
||||
description = {
|
||||
summary = "Lua serializer and pretty printer",
|
||||
homepage = "https://github.com/pkulchenko/serpent",
|
||||
maintainer = "Paul Kulchenko <paul@kulchenko.com>",
|
||||
license = "MIT",
|
||||
}
|
||||
|
||||
dependencies = {
|
||||
"lua >= 5.1, < 5.3",
|
||||
}
|
||||
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["serpent"] = "src/serpent.lua",
|
||||
},
|
||||
copy_directories = { "t" },
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
local n, v = "serpent", 0.25 -- (C) 2012-13 Paul Kulchenko; MIT License
|
||||
local n, v = "serpent", 0.26 -- (C) 2012-13 Paul Kulchenko; MIT License
|
||||
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
|
||||
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
|
||||
local badtype = {thread = true, userdata = true, cdata = true}
|
||||
@ -103,8 +103,26 @@ local function s(t, opts)
|
||||
return not name and body..warn or "do local "..body..sepr..tail.."return "..name..sepr.."end"
|
||||
end
|
||||
|
||||
local function deserialize(data, opts)
|
||||
local f, res = (loadstring or load)('return '..data)
|
||||
if not f then f, res = (loadstring or load)(data) end
|
||||
if not f then return f, res end
|
||||
if opts and opts.safe == false then return pcall(f) end
|
||||
|
||||
local count, thread = 0, coroutine.running()
|
||||
local h, m, c = debug.gethook(thread)
|
||||
debug.sethook(function (e, l) count = count + 1
|
||||
if count >= 3 then error("cannot call functions") end
|
||||
end, "c")
|
||||
local res = {pcall(f)}
|
||||
count = 0 -- set again, otherwise it's tripped on the next sethook
|
||||
debug.sethook(thread, h, m, c)
|
||||
return (table.unpack or unpack)(res)
|
||||
end
|
||||
|
||||
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
|
||||
return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s,
|
||||
load = deserialize,
|
||||
dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end,
|
||||
line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end,
|
||||
block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end }
|
||||
|
31
t/test.lua
31
t/test.lua
@ -261,8 +261,35 @@ do
|
||||
assert(called == false, "sorting is not called on numeric-only tables with maxnum: failed")
|
||||
end
|
||||
|
||||
-- test serializing large numeric-only tables
|
||||
do
|
||||
local ok, res = serpent.load(serpent.line(10))
|
||||
assert(ok and res == 10, "deserialization of simple number values: failed")
|
||||
|
||||
local ok, res = serpent.load(serpent.line(true))
|
||||
assert(ok and res == true, "deserialization of simple boolean values: failed")
|
||||
|
||||
local ok, res = serpent.load(serpent.line({3,4}))
|
||||
assert(ok and #res == 2 and res[1] == 3 and res[2] == 4,
|
||||
"deserialization of pretty-printed tables: failed")
|
||||
|
||||
local ok, res = serpent.load(serpent.dump({3,4}))
|
||||
assert(ok and #res == 2 and res[1] == 3 and res[2] == 4,
|
||||
"deserialization of serialized tables: failed")
|
||||
|
||||
local ok, res = serpent.load('{a = math.random()}')
|
||||
assert(not ok and res:find("cannot call functions"),
|
||||
"deserialization of unsafe values: failed")
|
||||
|
||||
local ok, res = serpent.load('{a = math.random()}', {safe = false})
|
||||
assert(ok and res and res.a > 0,
|
||||
"deserialization of unsafe values disabled: failed")
|
||||
end
|
||||
|
||||
print("All tests passed.")
|
||||
|
||||
do
|
||||
print("\nSerializing large numeric-only tables:")
|
||||
|
||||
local a, str = {}
|
||||
for i = 1, 100000 do a[i] = i end
|
||||
|
||||
@ -278,5 +305,3 @@ do
|
||||
str = serpent.dump(a, {sparse = false})
|
||||
print("dump/sparse=false: "..(os.clock() - start), #str)
|
||||
end
|
||||
|
||||
print("All tests passed.")
|
||||
|
Loading…
Reference in New Issue
Block a user