From b75caaf9591ff406e094679a6b82ac2ef7c089fa Mon Sep 17 00:00:00 2001 From: alemi Date: Mon, 5 Aug 2024 19:16:17 +0200 Subject: [PATCH] fix: lua glue uses structs directly --- src/ffi/lua.rs | 154 ++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 93 deletions(-) diff --git a/src/ffi/lua.rs b/src/ffi/lua.rs index 87470d6..7b5d66f 100644 --- a/src/ffi/lua.rs +++ b/src/ffi/lua.rs @@ -1,9 +1,8 @@ use std::io::Write; use std::sync::{mpsc, Arc, Mutex}; +use crate::api::Cursor; use crate::prelude::*; -use codemp_proto::{files::BufferNode, cursor::{RowCol, CursorPosition, CursorEvent}}; -use woot::crdt::Op; use mlua::prelude::*; use tokio::runtime::Runtime; @@ -41,188 +40,157 @@ impl GlobalState { } } -#[derive(Debug, thiserror::Error, derive_more::From, derive_more::Display)] -struct LuaCodempError(CodempError); - -impl From:: for LuaError { - fn from(value: LuaCodempError) -> Self { +impl From:: for LuaError { + fn from(value: CodempError) -> Self { LuaError::external(value) } } -// TODO put friendlier constructor directly in lib? -fn make_cursor(buffer: String, start_row: i32, start_col: i32, end_row: i32, end_col: i32) -> CursorPosition { - CursorPosition { - buffer: BufferNode::from(buffer), start: RowCol { row: start_row, col: start_col}, end: RowCol { row: end_row, col: end_col }, - } -} - fn id(_: &Lua, (): ()) -> LuaResult { Ok(STATE.client().user_id().to_string()) } /// join a remote workspace and start processing cursor events -fn join_workspace(_: &Lua, (session,): (String,)) -> LuaResult { +fn join_workspace(_: &Lua, (session,): (String,)) -> LuaResult { tracing::info!("joining workspace {}", session); - let ws = STATE.rt().block_on(async { STATE.client_mut().join_workspace(&session).await }) - .map_err(LuaCodempError::from)?; + let ws = STATE.rt().block_on(async { STATE.client_mut().join_workspace(&session).await })?; let cursor = ws.cursor(); Ok(cursor.into()) } fn login(_: &Lua, (username, password, workspace_id):(String, String, String)) -> LuaResult<()> { - Ok(STATE.rt().block_on(STATE.client().login(username, password, Some(workspace_id))).map_err(LuaCodempError::from)?) + Ok(STATE.rt().block_on(STATE.client().login(username, password, Some(workspace_id)))?) } -fn get_workspace(_: &Lua, (session,): (String,)) -> LuaResult> { - Ok(STATE.client().get_workspace(&session).map(LuaWorkspace)) +fn get_workspace(_: &Lua, (session,): (String,)) -> LuaResult> { + Ok(STATE.client().get_workspace(&session)) } -#[derive(Debug, derive_more::From)] -struct LuaOp(Op); -impl LuaUserData for LuaOp { } - -#[derive(derive_more::From)] -struct LuaWorkspace(Arc); -impl LuaUserData for LuaWorkspace { +impl LuaUserData for CodempWorkspace { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_method("create_buffer", |_, this, (name,):(String,)| { - Ok(STATE.rt().block_on(async { this.0.create(&name).await }).map_err(LuaCodempError::from)?) + Ok(STATE.rt().block_on(async { this.create(&name).await })?) }); methods.add_method("attach_buffer", |_, this, (name,):(String,)| { - Ok(LuaBufferController(STATE.rt().block_on(async { this.0.attach(&name).await }).map_err(LuaCodempError::from)?)) + Ok(STATE.rt().block_on(async { this.attach(&name).await })?) }); // TODO disconnect_buffer // TODO leave_workspace:w - methods.add_method("get_buffer", |_, this, (name,):(String,)| Ok(this.0.buffer_by_name(&name).map(LuaBufferController))); + methods.add_method("get_buffer", |_, this, (name,):(String,)| Ok(this.buffer_by_name(&name))); } fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("cursor", |_, this| Ok(LuaCursorController(this.0.cursor()))); - fields.add_field_method_get("filetree", |_, this| Ok(this.0.filetree())); + fields.add_field_method_get("cursor", |_, this| Ok(this.cursor())); + fields.add_field_method_get("filetree", |_, this| Ok(this.filetree())); // fields.add_field_method_get("users", |_, this| Ok(this.0.users())); // TODO } } - - -#[derive(Debug, derive_more::From)] -struct LuaCursorController(Arc); -impl LuaUserData for LuaCursorController { +impl LuaUserData for CodempCursorController { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this.0))); - methods.add_method("send", |_, this, (usr, sr, sc, er, ec):(String, i32, i32, i32, i32)| { - Ok(this.0.send(make_cursor(usr, sr, sc, er, ec)).map_err(LuaCodempError::from)?) + methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this))); + methods.add_method("send", |_, this, (buffer, start_row, start_col, end_row, end_col):(String, i32, i32, i32, i32)| { + Ok(this.send(CodempCursor { buffer, start: (start_row, start_col), end: (end_row, end_col), user: None })?) }); methods.add_method("try_recv", |_, this, ()| { - match this.0.try_recv() .map_err(LuaCodempError::from)? { - Some(x) => Ok(Some(LuaCursorEvent(x))), + match this.try_recv()? { + Some(x) => Ok(Some(x)), None => Ok(None), } }); methods.add_method("poll", |_, this, ()| { - STATE.rt().block_on(this.0.poll()) - .map_err(LuaCodempError::from)?; + STATE.rt().block_on(this.poll())?; Ok(()) }); } } -#[derive(Debug, derive_more::From)] -struct LuaCursorEvent(CursorEvent); -impl LuaUserData for LuaCursorEvent { +impl LuaUserData for Cursor { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("user", |_, this| Ok(this.0.user.id.clone())); - fields.add_field_method_get("position", |_, this| - Ok(LuaCursorPosition(this.0.position.clone())) - ); + fields.add_field_method_get("user", |_, this| Ok(this.user.map(|x| x.to_string()))); + fields.add_field_method_get("buffer", |_, this| Ok(this.buffer.clone())); + fields.add_field_method_get("start", |_, this| Ok(RowCol::from(this.start))); + fields.add_field_method_get("finish", |_, this| Ok(RowCol::from(this.end))); } } -#[derive(Debug, derive_more::From)] -struct LuaCursorPosition(CursorPosition); -impl LuaUserData for LuaCursorPosition { - fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("buffer", |_, this| Ok(this.0.buffer.path.clone())); - fields.add_field_method_get("start", |_, this| Ok(LuaRowCol(this.0.start.clone()))); - fields.add_field_method_get("finish", |_, this| Ok(LuaRowCol(this.0.end.clone()))); +pub struct RowCol { + pub row: i32, + pub col: i32, +} + +impl From<(i32, i32)> for RowCol { + fn from((row, col): (i32, i32)) -> Self { + Self { row, col } } } +impl LuaUserData for RowCol { + fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { + fields.add_field_method_get("row", |_, this| Ok(this.row)); + fields.add_field_method_get("col", |_, this| Ok(this.col)); + } +} -#[derive(Debug, derive_more::From)] -struct LuaBufferController(Arc); -impl LuaUserData for LuaBufferController { +impl LuaUserData for CodempBufferController { fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this.0))); + methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this))); methods.add_method("send", |_, this, (start, end, text): (usize, usize, String)| { Ok( - this.0.send( + this.send( CodempTextChange { span: start..end, content: text, } - ) - .map_err(LuaCodempError::from)? + )? ) }); methods.add_method("send_diff", |_, this, (content,):(String,)| { Ok( - this.0.send( - CodempTextChange::from_diff(&this.0.content(), &content) - ) - .map_err(LuaCodempError::from)? + this.send( + CodempTextChange::from_diff(&this.content(), &content) + )? ) }); methods.add_method("try_recv", |_, this, ()| { - match this.0.try_recv().map_err(LuaCodempError::from)? { - Some(x) => Ok(Some(LuaTextChange(x))), + match this.try_recv()? { + Some(x) => Ok(Some(x)), None => Ok(None), } }); methods.add_method("poll", |_, this, ()| { - STATE.rt().block_on(this.0.poll()) - .map_err(LuaCodempError::from)?; + STATE.rt().block_on(this.poll())?; Ok(()) }); } fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("content", |_, this| Ok(this.0.content())); + fields.add_field_method_get("content", |_, this| Ok(this.content())); } } -#[derive(Debug, derive_more::From)] -struct LuaTextChange(CodempTextChange); -impl LuaUserData for LuaTextChange { +impl LuaUserData for CodempOp { } + +impl LuaUserData for CodempTextChange { fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("content", |_, this| Ok(this.0.content.clone())); - fields.add_field_method_get("first", |_, this| Ok(this.0.span.start)); - fields.add_field_method_get("last", |_, this| Ok(this.0.span.end)); + 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("last", |_, this| Ok(this.span.end)); } fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { methods.add_meta_function(LuaMetaMethod::Call, |_, (start, end, txt): (usize, usize, String)| { - Ok(LuaTextChange(CodempTextChange { + Ok(CodempTextChange { span: start..end, content: txt, - })) + }) }); - methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this.0))); - methods.add_method("apply", |_, this, (txt,):(String,)| Ok(this.0.apply(&txt))); - } -} - -#[derive(Debug, derive_more::From)] -struct LuaRowCol(RowCol); -impl LuaUserData for LuaRowCol { - fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) { - fields.add_field_method_get("row", |_, this| Ok(this.0.row)); - fields.add_field_method_get("col", |_, this| Ok(this.0.col)); + methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| Ok(format!("{:?}", this))); + methods.add_method("apply", |_, this, (txt,):(String,)| Ok(this.apply(&txt))); } }