mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-17 18:11:30 +01:00
More work on config API
This commit is contained in:
parent
51f4f94eca
commit
2b40019045
14 changed files with 4837 additions and 113 deletions
|
@ -2,5 +2,4 @@
|
|||
members = [
|
||||
"pinnacle",
|
||||
"pinnacle_api",
|
||||
"pinnacle_api_ffi"
|
||||
]
|
||||
|
|
|
@ -15,20 +15,20 @@ use std::error::Error;
|
|||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
pinnacle_api::run()?;
|
||||
|
||||
// match tracing_subscriber::EnvFilter::try_from_default_env() {
|
||||
// Ok(env_filter) => {
|
||||
// tracing_subscriber::fmt()
|
||||
// .compact()
|
||||
// .with_env_filter(env_filter)
|
||||
// .init();
|
||||
// }
|
||||
// Err(_) => {
|
||||
// tracing_subscriber::fmt().compact().init();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// tracing::info!("Starting winit backend");
|
||||
// // crate::backend::winit::run_winit()?;
|
||||
match tracing_subscriber::EnvFilter::try_from_default_env() {
|
||||
Ok(env_filter) => {
|
||||
tracing_subscriber::fmt()
|
||||
.compact()
|
||||
.with_env_filter(env_filter)
|
||||
.init();
|
||||
}
|
||||
Err(_) => {
|
||||
tracing_subscriber::fmt().compact().init();
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!("Starting winit backend");
|
||||
crate::backend::winit::run_winit()?;
|
||||
// crate::backend::udev::run_udev()?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ pub struct State<B: Backend> {
|
|||
impl<B: Backend> State<B> {
|
||||
pub fn init(
|
||||
backend_data: B,
|
||||
display: &mut Display<State<B>>,
|
||||
display: &mut Display<Self>,
|
||||
loop_signal: LoopSignal,
|
||||
loop_handle: LoopHandle<'static, CalloopData<B>>,
|
||||
) -> Result<Self, Box<dyn Error>> {
|
||||
|
@ -106,19 +106,17 @@ impl<B: Backend> State<B> {
|
|||
loop_signal,
|
||||
loop_handle,
|
||||
clock: Clock::<Monotonic>::new()?,
|
||||
compositor_state: CompositorState::new::<State<B>>(&display_handle),
|
||||
data_device_state: DataDeviceState::new::<State<B>>(&display_handle),
|
||||
compositor_state: CompositorState::new::<Self>(&display_handle),
|
||||
data_device_state: DataDeviceState::new::<Self>(&display_handle),
|
||||
seat_state,
|
||||
pointer_location: (0.0, 0.0).into(),
|
||||
shm_state: ShmState::new::<State<B>>(&display_handle, vec![]),
|
||||
shm_state: ShmState::new::<Self>(&display_handle, vec![]),
|
||||
space: Space::<Window>::default(),
|
||||
cursor_status: CursorImageStatus::Default,
|
||||
output_manager_state: OutputManagerState::new_with_xdg_output::<State<B>>(
|
||||
&display_handle,
|
||||
),
|
||||
xdg_shell_state: XdgShellState::new::<State<B>>(&display_handle),
|
||||
viewporter_state: ViewporterState::new::<State<B>>(&display_handle),
|
||||
fractional_scale_manager_state: FractionalScaleManagerState::new::<State<B>>(
|
||||
output_manager_state: OutputManagerState::new_with_xdg_output::<Self>(&display_handle),
|
||||
xdg_shell_state: XdgShellState::new::<Self>(&display_handle),
|
||||
viewporter_state: ViewporterState::new::<Self>(&display_handle),
|
||||
fractional_scale_manager_state: FractionalScaleManagerState::new::<Self>(
|
||||
&display_handle,
|
||||
),
|
||||
|
||||
|
|
|
@ -7,3 +7,8 @@ edition = "2021"
|
|||
tracing = "0.1.37"
|
||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||
rkyv = { version = "0.7.42", features = ["validation", "strict"] }
|
||||
num_enum = "0.6.1"
|
||||
serde = { version = "1.0.164", features = ["derive"] }
|
||||
serde_json = { version = "1.0.96" }
|
||||
rmp-serde = { version = "1.1.1" }
|
||||
xkbcommon = { version = "0.5.0" }
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use std::{
|
||||
error::Error,
|
||||
io::Read,
|
||||
mem::size_of,
|
||||
os::{
|
||||
fd::AsRawFd,
|
||||
unix::net::{UnixListener, UnixStream},
|
||||
},
|
||||
os::unix::net::{UnixListener, UnixStream},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use crate::message::Msg;
|
||||
|
||||
pub mod message;
|
||||
|
||||
const SOCKET_PATH: &str = "/tmp/pinnacle_socket";
|
||||
|
||||
pub fn run() -> Result<(), Box<dyn Error>> {
|
||||
|
@ -20,32 +19,26 @@ pub fn run() -> Result<(), Box<dyn Error>> {
|
|||
|
||||
let listener = UnixListener::bind(SOCKET_PATH)?;
|
||||
|
||||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
std::thread::spawn(|| handle_client(stream));
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("Incoming stream error: {}", err);
|
||||
std::thread::spawn(move || {
|
||||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
std::thread::spawn(|| handle_client(stream));
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("Incoming stream error: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_client(mut stream: UnixStream) {
|
||||
let mut buf = [0u8; size_of::<Message>()];
|
||||
stream.read_exact(&mut buf).unwrap();
|
||||
fn handle_client(stream: UnixStream) {
|
||||
loop {
|
||||
let msg: Msg = rmp_serde::from_read(&stream).unwrap();
|
||||
|
||||
let thing = rkyv::check_archived_root::<Message>(&buf).unwrap();
|
||||
println!("{}", thing.number2);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(rkyv::Archive)]
|
||||
#[archive(check_bytes)]
|
||||
pub struct Message {
|
||||
number: u32,
|
||||
number2: u8,
|
||||
println!("{:?}", msg);
|
||||
}
|
||||
}
|
||||
|
|
28
pinnacle_api/src/message.rs
Normal file
28
pinnacle_api/src/message.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
// The MessagePack format for these is a one-element map where the element's key is the enum name and its
|
||||
// value is a map of the enum's values
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Msg {
|
||||
SetKeybind {
|
||||
key: u32,
|
||||
modifiers: Vec<Modifiers>,
|
||||
callback_id: u32,
|
||||
},
|
||||
SetMousebind {
|
||||
button: u8,
|
||||
},
|
||||
// Action(Action),
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Action {
|
||||
CloseWindow { client_id: Option<u32> },
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Modifiers {
|
||||
Shift,
|
||||
Ctrl,
|
||||
Alt,
|
||||
Super,
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
[package]
|
||||
name = "pinnacle_api_ffi"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
pinnacle_api = { path = "../pinnacle_api" }
|
|
@ -1,4 +0,0 @@
|
|||
use std::ffi::CString;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn send_message(number: u32, number2: u8) {}
|
|
@ -1,33 +0,0 @@
|
|||
local ffi = require("ffi")
|
||||
|
||||
local cdata = {}
|
||||
|
||||
-- http://www.catb.org/esr/structure-packing/
|
||||
function cdata:new_struct(name, struct)
|
||||
ffi.cdef(struct)
|
||||
|
||||
self.structs = self.structs or {}
|
||||
self.structs[name] = ffi.typeof(name)
|
||||
|
||||
self.pointers = self.pointers or {}
|
||||
self.pointers[name] = ffi.typeof(name .. "*")
|
||||
end
|
||||
|
||||
function cdata:set_struct(name, data)
|
||||
return ffi.new(self.structs[name], data)
|
||||
end
|
||||
|
||||
function cdata:encode(data)
|
||||
print("cast")
|
||||
local cast = ffi.cast("const char*", data)
|
||||
print("sizeof")
|
||||
local size = ffi.sizeof(data)
|
||||
print("string")
|
||||
return ffi.string(cast, size)
|
||||
end
|
||||
|
||||
function cdata:decode(name, data)
|
||||
return ffi.cast(self.pointers[name], data)[0]
|
||||
end
|
||||
|
||||
return cdata
|
15
pinnacle_api_lua/client.lua
Normal file
15
pinnacle_api_lua/client.lua
Normal file
|
@ -0,0 +1,15 @@
|
|||
local M = {}
|
||||
|
||||
---Close a window.
|
||||
---@param client_id integer? The id of the window you want closed, or nil to close the currently focused window, if any.
|
||||
function M.close_window(client_id)
|
||||
SendMsg({
|
||||
Action = {
|
||||
CloseWindow = {
|
||||
client_id = client_id or "nil",
|
||||
},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
|
@ -1,38 +1,54 @@
|
|||
-- require("luarocks.loader")
|
||||
|
||||
package.path = "./lib/?.lua;./lib/?/init.lua;" .. package.path
|
||||
package.cpath = "./lib/?.so;" .. package.cpath
|
||||
|
||||
local socket = require("posix.sys.socket")
|
||||
local unistd = require("posix.unistd")
|
||||
local ffi = require("cffi")
|
||||
local msgpack = require("lib.msgpack")
|
||||
|
||||
local SOCKET_PATH = "/tmp/pinnacle_socket"
|
||||
|
||||
local CONFIG_PATH = os.getenv("XDG_CONFIG_HOME") .. "/pinnacle/init.lua"
|
||||
|
||||
package.path = CONFIG_PATH .. ";" .. package.path
|
||||
|
||||
local sockaddr = {
|
||||
family = socket.AF_UNIX,
|
||||
path = SOCKET_PATH,
|
||||
}
|
||||
|
||||
local socket_fd = assert(socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0))
|
||||
local socket_fd = assert(socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0), "Failed to create socket")
|
||||
print("created socket at fd " .. socket_fd)
|
||||
|
||||
if 0 ~= socket.connect(socket_fd, sockaddr) then
|
||||
assert(false)
|
||||
assert(0 == socket.connect(socket_fd, sockaddr), "Failed to connect to Pinnacle socket")
|
||||
|
||||
function SendMsg(data)
|
||||
socket.send(socket_fd, msgpack.encode(data))
|
||||
end
|
||||
|
||||
ffi.cdef([[
|
||||
typedef struct Message { uint32_t number; uint8_t number2; } message;
|
||||
]])
|
||||
---@type function[]
|
||||
CallbackTable = {}
|
||||
|
||||
local type = ffi.typeof("message")
|
||||
assert(pcall(require, "pinnacle"), "config file not found")
|
||||
|
||||
local struct = ffi.new(type, {
|
||||
number = 12,
|
||||
number2 = 254,
|
||||
})
|
||||
local size = ffi.sizeof("message")
|
||||
local str = ffi.string(struct, size)
|
||||
|
||||
socket.send(socket_fd, str)
|
||||
-- local str = msgpack.encode({
|
||||
-- SetMousebind = { button = 6 },
|
||||
-- })
|
||||
-- local str = msgpack.encode({
|
||||
-- SetKeybind = {
|
||||
-- key = "This is a key",
|
||||
-- modifiers = { "ctrl", "boogers", "numpty" },
|
||||
-- },
|
||||
-- })
|
||||
-- print(str)
|
||||
--
|
||||
-- socket.send(socket_fd, str)
|
||||
|
||||
-- unistd.close(socket_fd)
|
||||
|
||||
-- local keys = require("keys")
|
||||
--
|
||||
-- local input = require("input")
|
||||
-- input.keybind({ "Shift", "Ctrl" }, keys.c, "CloseWindow")
|
||||
while true do
|
||||
end
|
||||
|
|
18
pinnacle_api_lua/input.lua
Normal file
18
pinnacle_api_lua/input.lua
Normal file
|
@ -0,0 +1,18 @@
|
|||
local M = {}
|
||||
|
||||
---Set a keybind. If called on an already existing keybind, it gets replaced.
|
||||
---@param key Keys The key for the keybind. NOTE: uppercase and lowercase characters are considered different.
|
||||
---@param modifiers Modifiers[] Which modifiers need to be pressed for the keybind to trigger.
|
||||
---@param action function What to run.
|
||||
function M.keybind(modifiers, key, action)
|
||||
table.insert(CallbackTable, action)
|
||||
SendMsg({
|
||||
SetKeybind = {
|
||||
modifiers = modifiers,
|
||||
key = key,
|
||||
callback_id = #CallbackTable,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
4318
pinnacle_api_lua/keys.lua
Normal file
4318
pinnacle_api_lua/keys.lua
Normal file
File diff suppressed because it is too large
Load diff
378
pinnacle_api_lua/lib/msgpack.lua
Normal file
378
pinnacle_api_lua/lib/msgpack.lua
Normal file
|
@ -0,0 +1,378 @@
|
|||
--[[----------------------------------------------------------------------------
|
||||
|
||||
MessagePack encoder / decoder written in pure Lua 5.3 / Lua 5.4
|
||||
written by Sebastian Steinhauer <s.steinhauer@yahoo.de>
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
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 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.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
--]]
|
||||
----------------------------------------------------------------------------
|
||||
local pack, unpack = string.pack, string.unpack
|
||||
local mtype, utf8len = math.type, utf8.len
|
||||
local tconcat, tunpack = table.concat, table.unpack
|
||||
local ssub = string.sub
|
||||
local type, pcall, pairs, select = type, pcall, pairs, select
|
||||
|
||||
--[[----------------------------------------------------------------------------
|
||||
|
||||
Encoder
|
||||
|
||||
--]]
|
||||
----------------------------------------------------------------------------
|
||||
local encode_value -- forward declaration
|
||||
|
||||
local function is_an_array(value)
|
||||
local expected = 1
|
||||
for k in pairs(value) do
|
||||
if k ~= expected then
|
||||
return false
|
||||
end
|
||||
expected = expected + 1
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local encoder_functions = {
|
||||
["nil"] = function()
|
||||
return pack("B", 0xc0)
|
||||
end,
|
||||
["boolean"] = function(value)
|
||||
if value then
|
||||
return pack("B", 0xc3)
|
||||
else
|
||||
return pack("B", 0xc2)
|
||||
end
|
||||
end,
|
||||
["number"] = function(value)
|
||||
if mtype(value) == "integer" then
|
||||
if value >= 0 then
|
||||
if value < 128 then
|
||||
return pack("B", value)
|
||||
elseif value <= 0xff then
|
||||
return pack("BB", 0xcc, value)
|
||||
elseif value <= 0xffff then
|
||||
return pack(">BI2", 0xcd, value)
|
||||
elseif value <= 0xffffffff then
|
||||
return pack(">BI4", 0xce, value)
|
||||
else
|
||||
return pack(">BI8", 0xcf, value)
|
||||
end
|
||||
else
|
||||
if value >= -32 then
|
||||
return pack("B", 0xe0 + (value + 32))
|
||||
elseif value >= -128 then
|
||||
return pack("Bb", 0xd0, value)
|
||||
elseif value >= -32768 then
|
||||
return pack(">Bi2", 0xd1, value)
|
||||
elseif value >= -2147483648 then
|
||||
return pack(">Bi4", 0xd2, value)
|
||||
else
|
||||
return pack(">Bi8", 0xd3, value)
|
||||
end
|
||||
end
|
||||
else
|
||||
local test = unpack("f", pack("f", value))
|
||||
if test == value then -- check if we can use float
|
||||
return pack(">Bf", 0xca, value)
|
||||
else
|
||||
return pack(">Bd", 0xcb, value)
|
||||
end
|
||||
end
|
||||
end,
|
||||
["string"] = function(value)
|
||||
local len = #value
|
||||
if utf8len(value) then -- check if it is a real utf8 string or just byte junk
|
||||
if value == "nil" then -- TODO: maybe just check for nil in api functions
|
||||
return pack("B", 0xc0)
|
||||
elseif len < 32 then
|
||||
return pack("B", 0xa0 + len) .. value
|
||||
elseif len < 256 then
|
||||
return pack(">Bs1", 0xd9, value)
|
||||
elseif len < 65536 then
|
||||
return pack(">Bs2", 0xda, value)
|
||||
else
|
||||
return pack(">Bs4", 0xdb, value)
|
||||
end
|
||||
else -- encode it as byte-junk :)
|
||||
if len < 256 then
|
||||
return pack(">Bs1", 0xc4, value)
|
||||
elseif len < 65536 then
|
||||
return pack(">Bs2", 0xc5, value)
|
||||
else
|
||||
return pack(">Bs4", 0xc6, value)
|
||||
end
|
||||
end
|
||||
end,
|
||||
["table"] = function(value)
|
||||
if is_an_array(value) then -- it seems to be a proper Lua array
|
||||
local elements = {}
|
||||
for i, v in pairs(value) do
|
||||
elements[i] = encode_value(v)
|
||||
end
|
||||
|
||||
local length = #elements
|
||||
if length < 16 then
|
||||
return pack(">B", 0x90 + length) .. tconcat(elements)
|
||||
elseif length < 65536 then
|
||||
return pack(">BI2", 0xdc, length) .. tconcat(elements)
|
||||
else
|
||||
return pack(">BI4", 0xdd, length) .. tconcat(elements)
|
||||
end
|
||||
else -- encode as a map
|
||||
local elements = {}
|
||||
for k, v in pairs(value) do
|
||||
elements[#elements + 1] = encode_value(k)
|
||||
elements[#elements + 1] = encode_value(v)
|
||||
end
|
||||
|
||||
local length = #elements // 2
|
||||
if length < 16 then
|
||||
return pack(">B", 0x80 + length) .. tconcat(elements)
|
||||
elseif length < 65536 then
|
||||
return pack(">BI2", 0xde, length) .. tconcat(elements)
|
||||
else
|
||||
return pack(">BI4", 0xdf, length) .. tconcat(elements)
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
encode_value = function(value)
|
||||
return encoder_functions[type(value)](value)
|
||||
end
|
||||
|
||||
local function encode(...)
|
||||
local data = {}
|
||||
for i = 1, select("#", ...) do
|
||||
data[#data + 1] = encode_value(select(i, ...))
|
||||
end
|
||||
return tconcat(data)
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------------
|
||||
|
||||
Decoder
|
||||
|
||||
--]]
|
||||
----------------------------------------------------------------------------
|
||||
local decode_value -- forward declaration
|
||||
|
||||
local function decode_array(data, position, length)
|
||||
local elements, value = {}
|
||||
for i = 1, length do
|
||||
value, position = decode_value(data, position)
|
||||
elements[i] = value
|
||||
end
|
||||
return elements, position
|
||||
end
|
||||
|
||||
local function decode_map(data, position, length)
|
||||
local elements, key, value = {}
|
||||
for i = 1, length do
|
||||
key, position = decode_value(data, position)
|
||||
value, position = decode_value(data, position)
|
||||
elements[key] = value
|
||||
end
|
||||
return elements, position
|
||||
end
|
||||
|
||||
local decoder_functions = {
|
||||
[0xc0] = function(data, position)
|
||||
return nil, position
|
||||
end,
|
||||
[0xc2] = function(data, position)
|
||||
return false, position
|
||||
end,
|
||||
[0xc3] = function(data, position)
|
||||
return true, position
|
||||
end,
|
||||
[0xc4] = function(data, position)
|
||||
return unpack(">s1", data, position)
|
||||
end,
|
||||
[0xc5] = function(data, position)
|
||||
return unpack(">s2", data, position)
|
||||
end,
|
||||
[0xc6] = function(data, position)
|
||||
return unpack(">s4", data, position)
|
||||
end,
|
||||
[0xca] = function(data, position)
|
||||
return unpack(">f", data, position)
|
||||
end,
|
||||
[0xcb] = function(data, position)
|
||||
return unpack(">d", data, position)
|
||||
end,
|
||||
[0xcc] = function(data, position)
|
||||
return unpack(">B", data, position)
|
||||
end,
|
||||
[0xcd] = function(data, position)
|
||||
return unpack(">I2", data, position)
|
||||
end,
|
||||
[0xce] = function(data, position)
|
||||
return unpack(">I4", data, position)
|
||||
end,
|
||||
[0xcf] = function(data, position)
|
||||
return unpack(">I8", data, position)
|
||||
end,
|
||||
[0xd0] = function(data, position)
|
||||
return unpack(">b", data, position)
|
||||
end,
|
||||
[0xd1] = function(data, position)
|
||||
return unpack(">i2", data, position)
|
||||
end,
|
||||
[0xd2] = function(data, position)
|
||||
return unpack(">i4", data, position)
|
||||
end,
|
||||
[0xd3] = function(data, position)
|
||||
return unpack(">i8", data, position)
|
||||
end,
|
||||
[0xd9] = function(data, position)
|
||||
return unpack(">s1", data, position)
|
||||
end,
|
||||
[0xda] = function(data, position)
|
||||
return unpack(">s2", data, position)
|
||||
end,
|
||||
[0xdb] = function(data, position)
|
||||
return unpack(">s4", data, position)
|
||||
end,
|
||||
[0xdc] = function(data, position)
|
||||
local length
|
||||
length, position = unpack(">I2", data, position)
|
||||
return decode_array(data, position, length)
|
||||
end,
|
||||
[0xdd] = function(data, position)
|
||||
local length
|
||||
length, position = unpack(">I4", data, position)
|
||||
return decode_array(data, position, length)
|
||||
end,
|
||||
[0xde] = function(data, position)
|
||||
local length
|
||||
length, position = unpack(">I2", data, position)
|
||||
return decode_map(data, position, length)
|
||||
end,
|
||||
[0xdf] = function(data, position)
|
||||
local length
|
||||
length, position = unpack(">I4", data, position)
|
||||
return decode_map(data, position, length)
|
||||
end,
|
||||
}
|
||||
|
||||
-- add fix-array, fix-map, fix-string, fix-int stuff
|
||||
for i = 0x00, 0x7f do
|
||||
decoder_functions[i] = function(data, position)
|
||||
return i, position
|
||||
end
|
||||
end
|
||||
for i = 0x80, 0x8f do
|
||||
decoder_functions[i] = function(data, position)
|
||||
return decode_map(data, position, i - 0x80)
|
||||
end
|
||||
end
|
||||
for i = 0x90, 0x9f do
|
||||
decoder_functions[i] = function(data, position)
|
||||
return decode_array(data, position, i - 0x90)
|
||||
end
|
||||
end
|
||||
for i = 0xa0, 0xbf do
|
||||
decoder_functions[i] = function(data, position)
|
||||
local length = i - 0xa0
|
||||
return ssub(data, position, position + length - 1), position + length
|
||||
end
|
||||
end
|
||||
for i = 0xe0, 0xff do
|
||||
decoder_functions[i] = function(data, position)
|
||||
return -32 + (i - 0xe0), position
|
||||
end
|
||||
end
|
||||
|
||||
decode_value = function(data, position)
|
||||
local byte, value
|
||||
byte, position = unpack("B", data, position)
|
||||
value, position = decoder_functions[byte](data, position)
|
||||
return value, position
|
||||
end
|
||||
|
||||
--[[----------------------------------------------------------------------------
|
||||
|
||||
Interface
|
||||
|
||||
--]]
|
||||
----------------------------------------------------------------------------
|
||||
return {
|
||||
_AUTHOR = "Sebastian Steinhauer <s.steinhauer@yahoo.de>",
|
||||
_VERSION = "0.6.1",
|
||||
|
||||
-- primary encode function
|
||||
encode = function(...)
|
||||
local data, ok = {}
|
||||
for i = 1, select("#", ...) do
|
||||
ok, data[i] = pcall(encode_value, select(i, ...))
|
||||
if not ok then
|
||||
return nil, "cannot encode MessagePack"
|
||||
end
|
||||
end
|
||||
return tconcat(data)
|
||||
end,
|
||||
|
||||
-- encode just one value
|
||||
encode_one = function(value)
|
||||
local ok, data = pcall(encode_value, value)
|
||||
if ok then
|
||||
return data
|
||||
else
|
||||
return nil, "cannot encode MessagePack"
|
||||
end
|
||||
end,
|
||||
|
||||
-- primary decode function
|
||||
decode = function(data, position)
|
||||
local values, value, ok = {}
|
||||
position = position or 1
|
||||
while position <= #data do
|
||||
ok, value, position = pcall(decode_value, data, position)
|
||||
if ok then
|
||||
values[#values + 1] = value
|
||||
else
|
||||
return nil, "cannot decode MessagePack"
|
||||
end
|
||||
end
|
||||
return tunpack(values)
|
||||
end,
|
||||
|
||||
-- decode just one value
|
||||
decode_one = function(data, position)
|
||||
local value, ok
|
||||
ok, value, position = pcall(decode_value, data, position or 1)
|
||||
if ok then
|
||||
return value, position
|
||||
else
|
||||
return nil, "cannot decode MessagePack"
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
--[[----------------------------------------------------------------------------
|
||||
--]]
|
||||
----------------------------------------------------------------------------
|
Loading…
Reference in a new issue