util.jsonpointer: Resolve JSON Pointers per RFC 6901

This commit is contained in:
Kim Alvefur 2021-12-29 16:52:09 +01:00
parent 9b31c8175e
commit d8017615c7
3 changed files with 87 additions and 1 deletions

View file

@ -110,7 +110,7 @@ vpath %.tl teal-src/
tl -I teal-src/ --gen-compat off --gen-target 5.1 gen $^ -o $@
-lua-format -i $@
teal: util/jsonschema.lua util/datamapper.lua
teal: util/jsonschema.lua util/datamapper.lua util/jsonpointer.lua
util/%.so:
$(MAKE) install -C util-src

View file

@ -0,0 +1,46 @@
local enum ptr_error
"invalid-table"
"invalid-path"
end
local function unescape_token(escaped_token : string) : string
local unescaped = escaped_token:gsub("~1", "/"):gsub("~0", "~")
return unescaped
end
local function resolve_json_pointer(ref : table, path : string) : any, ptr_error
local ptr_len = #path+1
for part, pos in path:gmatch("/([^/]*)()") do
local token = unescape_token(part)
if not ref is table then
return nil
end
local idx = next(ref)
local new_ref : any
if idx is string then
new_ref = ref[token]
elseif idx is integer then
local i = tonumber(token)
if token == "-" then i = #ref + 1 end
new_ref = ref[i]
else
return nil, "invalid-table"
end
if pos as integer == ptr_len then
return new_ref
elseif new_ref is table then
ref = new_ref
elseif not ref is table then
return nil, "invalid-path"
end
end
return ref
end
return {
resolve = resolve_json_pointer,
}

40
util/jsonpointer.lua Normal file
View file

@ -0,0 +1,40 @@
local function unescape_token(escaped_token)
local unescaped = escaped_token:gsub("~1", "/"):gsub("~0", "~")
return unescaped
end
local function resolve_json_pointer(ref, path)
local ptr_len = #path + 1
for part, pos in path:gmatch("/([^/]*)()") do
local token = unescape_token(part)
if not (type(ref) == "table") then
return nil
end
local idx = next(ref)
local new_ref
if type(idx) == "string" then
new_ref = ref[token]
elseif math.type(idx) == "integer" then
local i = tonumber(token)
if token == "-" then
i = #ref + 1
end
new_ref = ref[i]
else
return nil, "invalid-table"
end
if pos == ptr_len then
return new_ref
elseif type(new_ref) == "table" then
ref = new_ref
elseif not (type(ref) == "table") then
return nil, "invalid-path"
end
end
return ref
end
return { resolve = resolve_json_pointer }