fix: updated lua ffi

now the client is given to lua
This commit is contained in:
əlemi 2024-08-08 02:48:21 +02:00
parent a9bab2bb03
commit e1ba683fd0
Signed by: alemi
GPG key ID: A4895B84D311642C

View file

@ -1,84 +1,60 @@
use std::io::Write; use std::io::Write;
use std::sync::atomic::AtomicBool;
use std::sync::Mutex; use std::sync::Mutex;
use crate::api::Cursor; use crate::api::Cursor;
use crate::prelude::*; use crate::prelude::*;
use mlua::prelude::*; use mlua::prelude::*;
use tokio::runtime::Runtime;
use tokio::sync::broadcast; use tokio::sync::broadcast;
lazy_static::lazy_static!{ lazy_static::lazy_static!{
// TODO use a runtime::Builder::new_current_thread() runtime to not behave like malware // TODO use a runtime::Builder::new_current_thread() runtime to not behave like malware
static ref STATE : GlobalState = GlobalState::default(); static ref RT : tokio::runtime::Runtime = tokio::runtime::Builder::new_current_thread().enable_all().build().expect("could not create tokio runtime");
static ref LOG : broadcast::Sender<String> = broadcast::channel(32).0; static ref LOG : broadcast::Sender<String> = broadcast::channel(32).0;
} }
struct GlobalState { fn runtime_drive_forever(_: &Lua, ():()) -> LuaResult<()> {
client: std::sync::RwLock<CodempClient>, std::thread::spawn(|| RT.block_on(std::future::pending::<()>()));
runtime: Runtime, Ok(())
}
impl Default for GlobalState {
fn default() -> Self {
let rt = Runtime::new().expect("could not create tokio runtime");
let addr = std::env::var("CODEMP_SERVER_ADDRESS").unwrap_or_else(|_|"http://codemp.alemi.dev:50053".to_string());
let client = rt.block_on(
CodempClient::new(&addr)
).expect("could not connect to codemp servers");
GlobalState { client: std::sync::RwLock::new(client), runtime: rt }
}
}
impl GlobalState {
fn client(&self) -> std::sync::RwLockReadGuard<CodempClient> {
self.client.read().unwrap()
}
fn client_mut(&self) -> std::sync::RwLockWriteGuard<CodempClient> {
self.client.write().unwrap()
}
fn rt(&self) -> &Runtime {
&self.runtime
}
} }
impl From::<CodempError> for LuaError { impl From::<CodempError> for LuaError {
fn from(value: CodempError) -> Self { fn from(value: CodempError) -> Self {
LuaError::external(value) LuaError::RuntimeError(value.to_string())
} }
} }
fn id(_: &Lua, (): ()) -> LuaResult<String> { fn connect(_: &Lua, (host, username, password): (String, String, String)) -> LuaResult<CodempClient> {
Ok(STATE.client().user_id().to_string()) Ok(RT.block_on(CodempClient::new(host, username, password))?)
} }
impl LuaUserData for CodempClient {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("id", |_, this| Ok(this.user_id().to_string()));
}
/// join a remote workspace and start processing cursor events fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
fn join_workspace(_: &Lua, (session,): (String,)) -> LuaResult<CodempCursorController> { // join a remote workspace and start processing cursor events
methods.add_method("join_workspace", |_, this, (session,):(String,)| {
tracing::info!("joining workspace {}", session); tracing::info!("joining workspace {}", session);
let ws = STATE.rt().block_on(async { STATE.client_mut().join_workspace(&session).await })?; let ws = RT.block_on(async { this.join_workspace(&session).await })?;
let cursor = ws.cursor(); let cursor = ws.cursor();
Ok(cursor.into()) Ok(cursor)
});
methods.add_method("get_workspace", |_, this, (session,):(String,)| Ok(this.get_workspace(&session)));
} }
fn login(_: &Lua, (username, password, workspace_id):(String, String, String)) -> LuaResult<()> {
Ok(STATE.rt().block_on(STATE.client().login(username, password, Some(workspace_id)))?)
} }
fn get_workspace(_: &Lua, (session,): (String,)) -> LuaResult<Option<CodempWorkspace>> {
Ok(STATE.client().get_workspace(&session))
}
impl LuaUserData for CodempWorkspace { impl LuaUserData for CodempWorkspace {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_method("create_buffer", |_, this, (name,):(String,)| { methods.add_method("create_buffer", |_, this, (name,):(String,)| {
Ok(STATE.rt().block_on(async { this.create(&name).await })?) Ok(RT.block_on(async { this.create(&name).await })?)
}); });
methods.add_method("attach_buffer", |_, this, (name,):(String,)| { methods.add_method("attach_buffer", |_, this, (name,):(String,)| {
Ok(STATE.rt().block_on(async { this.attach(&name).await })?) Ok(RT.block_on(async { this.attach(&name).await })?)
}); });
// TODO disconnect_buffer // TODO disconnect_buffer
@ -107,7 +83,7 @@ impl LuaUserData for CodempCursorController {
} }
}); });
methods.add_method("poll", |_, this, ()| { methods.add_method("poll", |_, this, ()| {
STATE.rt().block_on(this.poll())?; RT.block_on(this.poll())?;
Ok(()) Ok(())
}); });
} }
@ -122,9 +98,9 @@ impl LuaUserData for Cursor {
} }
} }
pub struct RowCol { struct RowCol {
pub row: i32, row: i32,
pub col: i32, col: i32,
} }
impl From<(i32, i32)> for RowCol { impl From<(i32, i32)> for RowCol {
@ -147,7 +123,8 @@ impl LuaUserData for CodempBufferController {
Ok( Ok(
this.send( this.send(
CodempTextChange { CodempTextChange {
span: start..end, start: start as u32,
end: end as u32,
content: text, content: text,
} }
)? )?
@ -167,7 +144,7 @@ impl LuaUserData for CodempBufferController {
} }
}); });
methods.add_method("poll", |_, this, ()| { methods.add_method("poll", |_, this, ()| {
STATE.rt().block_on(this.poll())?; RT.block_on(this.poll())?;
Ok(()) Ok(())
}); });
} }
@ -182,14 +159,15 @@ impl LuaUserData for CodempOp { }
impl LuaUserData for CodempTextChange { impl LuaUserData for CodempTextChange {
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("content", |_, this| Ok(this.content.clone())); fields.add_field_method_get("content", |_, this| Ok(this.content.clone()));
fields.add_field_method_get("first", |_, this| Ok(this.span.start)); fields.add_field_method_get("first", |_, this| Ok(this.start));
fields.add_field_method_get("last", |_, this| Ok(this.span.end)); fields.add_field_method_get("last", |_, this| Ok(this.end));
} }
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_function(LuaMetaMethod::Call, |_, (start, end, txt): (usize, usize, String)| { methods.add_meta_function(LuaMetaMethod::Call, |_, (start, end, txt): (usize, usize, String)| {
Ok(CodempTextChange { Ok(CodempTextChange {
span: start..end, start: start as u32,
end: end as u32,
content: txt, content: txt,
}) })
}); });
@ -260,15 +238,15 @@ fn get_logger(_: &Lua, (): ()) -> LuaResult<LuaLogger> {
fn codemp_lua(lua: &Lua) -> LuaResult<LuaTable> { fn codemp_lua(lua: &Lua) -> LuaResult<LuaTable> {
let exports = lua.create_table()?; let exports = lua.create_table()?;
// core proto functions // entrypoint
exports.set("login", lua.create_function(login)?)?; exports.set("connect", lua.create_function(connect)?)?;
exports.set("join_workspace", lua.create_function(join_workspace)?)?;
// state helpers // runtime
exports.set("get_workspace", lua.create_function(get_workspace)?)?; exports.set("spawn_runtime_driver", lua.create_function(runtime_drive_forever)?)?;
// debug
exports.set("id", lua.create_function(id)?)?; // logging
exports.set("get_logger", lua.create_function(get_logger)?)?;
exports.set("setup_logger", lua.create_function(setup_logger)?)?; exports.set("setup_logger", lua.create_function(setup_logger)?)?;
exports.set("get_logger", lua.create_function(get_logger)?)?;
Ok(exports) Ok(exports)
} }