From 372fe38c643bf76af83bfde4344c444442c0a681 Mon Sep 17 00:00:00 2001 From: flamendless Date: Tue, 19 May 2020 13:05:28 +0800 Subject: [PATCH] initial push --- LICENSE | 19 ++++++++++ README.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ arson.lua | 77 +++++++++++++++++++++++++++++++++++++++++ main.lua | 62 +++++++++++++++++++++++++++++++++ 4 files changed, 259 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 arson.lua create mode 100644 main.lua diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ea47f0d --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 flamendless + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..958ea06 --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# ARSON + +A library-companion to register custom data types that can be encoded and decoded for [json.lua](https://github.com/rxi/json.lua). + +## Why Arson? + +It is from `RSON`, which is derived from `Register-JSON`. I know it does not make any sense. But is sounds cool. + +## How to use: + +Require it as such: `local arson = require("arson")` + +or if it is nested in a directory: `local arson = require("folder.folder.arson")` + +## Custom Data/Class Prerequisite + +Your class or object must have the public field `type`. This will be used by Arson to determine whether a table stored in the data is to be encoded/decoded + +Example: +```lua +local my_custom_class = { + text = "Hello, World!", + type = "my_custom_class" --IMPORTANT +} +``` + +You can check the [main.lua](https://github.com/flamendless/arson.lua/blob/master/main.lua) as an example. It has descriptive comments. + +## API + +* Arson.register - register your own custom data/class that can be encoded and decoded + +Example: +```lua +--(type_name : string, on_encode : function, on_decode : function) +--returns nothing + +arson.register("custom_vec2_class", + function(data) + return { x = data.x, y = data.y } + end, + function(data) + return my_custom_vec2_class:new(data.x, data.y) + end) +``` + +* Arson.unregister - unregister an already added custom data/class + +Example: +```lua +--(type_name : string) +--returns nothing + +arson.unregister("custom_class") --will error +arson.unregister("custom_vec2_class") +``` + +* Arson.encode - encode a table + +Example: +```lua +--(t : table) +--returns custom_encoded_table : table + +local data = { + 1, 2, 3, custom_vec2_class(1, 1), + foo = { 4, 5, 6 }, + bar = custom_vec2_class(2, 2), +} +local custom_data = arson.encode(data) + +--[[ +returned table: +{ +1, 2, 3, { x = 1, y = 1, type = "custom_vec2_class" }, +foo = { 4, 5, 6 }, +bar = { x = 1, y = 1, type = "custom_vec2_class" } +} +--]] + +--the custom_data table can now be used with json.lua +local str_json = json.encode(custom_data) +``` + +* Arson.decode - decode a table. It will modify the table passed as it will replace custom data with the decoded one + +Example: +```lua +--(t : table) +--returns nothing + +--first let us decode the str_json +local json_decoded = json.decode(str_json) + +--then finally decode custom data/class +arson.decode(json_decoded) +``` + +## LICENSE + +See MIT License [file here](https://github.com/flamendless/arson.lua/blob/master/LICENSE) diff --git a/arson.lua b/arson.lua new file mode 100644 index 0000000..04114e4 --- /dev/null +++ b/arson.lua @@ -0,0 +1,77 @@ +local Arson = {} + +local custom_types = {} + +local encode_custom = function(t) + assert(type(t) == "table", "Passed argument must be of type 'table'") + local custom = custom_types[t.type] + if custom then + return true, custom.on_encode, t.type + else + return false + end +end + +local decode_custom = function(t) + assert(type(t) == "table", "Passed argument must be of type 'table'") + local custom = custom_types[t.type] + if custom then + return true, custom.on_decode + else + return false + end +end + +function Arson.register(type_name, on_encode, on_decode) + assert(type(type_name) == "string", "Passed argument 'type_name' must be of type 'string'") + assert(custom_types[type_name], "Passed 'type_name' was already registered") + assert(type(on_encode) == "function", "Passed argument 'on_encode' must be of type 'function'") + assert(type(on_decode) == "function", "Passed argument 'on_decode' must be of type 'function'") + custom_types[type_name] = { + on_encode = on_encode, + on_decode = on_decode + } +end + +function Arson.unregister(type_name) + assert(type(type_name) == "string", "Passed argument 'type_name' must be of type 'string'") + assert(custom_types[type_name], "Passed 'type_name' is not registered") + custom_types[type_name] = nil +end + +function Arson.encode(t, tmp) + assert(type(t) == "table", "Passed argument 't' must be of type 'table'") + local tmp = tmp or {} + for k, v in pairs(t) do + if type(v) == "table" then + local is_custom, on_encode, type_name = encode_custom(v) + if is_custom then + local custom_data = on_encode(v) + custom_data.type = type_name + tmp[k] = custom_data + else + tmp[k] = {} + Arson.encode(v, tmp[k]) + end + else + tmp[k] = v + end + end + return tmp +end + +function Arson.decode(t) + assert(type(t) == "table", "Passed argument 't' must be of type 'table'") + for k, v in pairs(t) do + if type(v) == "table" then + local is_custom, on_decode = decode_custom(v) + if is_custom then + t[k] = on_decode(v) + else + Arson.decode(v) + end + end + end +end + +return Arson diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..f3ad9b6 --- /dev/null +++ b/main.lua @@ -0,0 +1,62 @@ +local arson = require("arson") +local json = require("json") --https://github.com/rxi/json.lua +local inspect = require("inspect") --https://github.com/kikito/inspect.lua + +--Let's say this is your custom vec2 class +local custom_vec2_class = { + x = 0, + y = 0, + type = "my_custom_vec2" --important field your custom class must have +} + +--For the vec3 version +local custom_vec3_class = { + x = 0, + y = 0, + z = 0, + type = "my_custom_vec3" --important field your custom class must have +} + +local vec2 = create_new_vec2(0, 0) --a sample constructor of your own class +local vec3 = create_new_vec3(0, 0, 0) + +local data_to_store = { + 1, 2, 3, "Hello", "World", + vec2, vec2, vec3, vec3, + create_new_vec2(1, 1), + create_new_vec3(1, 1, 1), + { + 4, 5, 6, + foo = vec2, + foofoo = vec3, + bar = { 7, 8, 9 } + } +} + +arson.register("my_custom_vec2", --Must match the 'type' field in your custom data + function(data) --on encode function + return { x = data.x, y = data.y } --this will be stored in the JSON + end, + function(data) --on decode function + return create_new_vec2(data.x, data.y) --this will be the final data after decoding + end) + +arson.register("my_custom_vec3", + function(data) + return { x = data.x, y = data.y, z = data.z } + end, + function(data) + return create_new_vec3(data.x, data.y, data.z) + end) + +--NOTE that the 'data' you will get upon the `on_decode` function is dependent on what you have store during the `on_encode` function + +local custom_encoded = arson.encode(data_to_store) +print(inspect(custom_encoded)) + +local str_json = json.encode(custom_encoded) +print(str_json) + +local decoded = json.decode(str_json) +arson.decode(decoded) +print(inspect(decoded))