Parcourir la source

Typo, buffer and function renaming.

Implemented simple buffer object so it is a little bit easier to deal with binary data.
Fixed small typo.
Renamed all functions and methods, so it is more consistent with gmod's naming.
IVogel il y a 2 ans
Parent
commit
efd2eaf4db
5 fichiers modifiés avec 378 ajouts et 51 suppressions
  1. 2 1
      Cargo.toml
  2. 337 0
      src/buffer.rs
  3. 17 30
      src/ldb.rs
  4. 12 2
      src/lib.rs
  5. 10 18
      src/ltree.rs

+ 2 - 1
Cargo.toml

@@ -10,4 +10,5 @@ crate-type = ["cdylib"]
 lua-shared = {git = "http://git.thetha.wtf/ivogel/lua-shared.git"}
 sled = "0.34.7"
 bincode = "1.3.3"
-serde = "1.0.139"
+serde = "1.0.139"
+paste = "1.0"

+ 337 - 0
src/buffer.rs

@@ -0,0 +1,337 @@
+use lua_shared as lua;
+use lua_shared::lua_State;
+use paste::paste;
+use std::u64;
+
+use crate::{check_slice, insert_function};
+macro_rules! def_rw {
+    ($type_name:ty) => {
+        paste! {
+            fn [<read_ $type_name>](&mut self) -> Option<$type_name> {
+                if self.0.len() == 0 || self.1 + std::mem::size_of::<$type_name>() > self.0.len() {
+                    return None
+                }
+                let data = self.read(std::mem::size_of::<$type_name>())?;
+                unsafe {Some($type_name::from_le(*std::mem::transmute::<_, &$type_name>(data.as_ptr())))}
+            }
+            fn [<write_ $type_name>](&mut self, value: $type_name) {
+                self.write(&value.to_le_bytes());
+            }
+        }
+    };
+    ($($type_name:ty )+) => {
+        $(def_rw!($type_name);)+
+    };
+}
+
+macro_rules! def_lmint {
+    ($name:ident, $type_name:ty) => {
+        paste! {
+            fn [<lm_read_ $name>](state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+                unsafe {
+                    let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+                    match this.[<read_ $type_name>]() {
+                        Some(val) => {
+                            lua::pushinteger(state, val as _);
+                        }
+                        None => {
+                            lua::pushnil(state)
+                        }
+                    }
+                    Ok(1)
+                }
+            }
+            fn [<lm_write_ $name>](state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+                unsafe {
+                    let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+                    this.[<write_ $type_name>](lua::Lcheckinteger(state, 2) as _);
+                    Ok(0)
+                }
+            }
+        }
+    };
+}
+
+macro_rules! def_lmfloat {
+    ($name:ident, $type_name:ty) => {
+        paste! {
+            fn [<lm_read_ $name>](state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+                unsafe {
+                    let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+                    match this.[<read_ $type_name>]() {
+                        Some(val) => {
+                            lua::pushnumber(state, val as _);
+                        }
+                        None => {
+                            lua::pushnil(state)
+                        }
+                    }
+                    Ok(1)
+                }
+            }
+            fn [<lm_write_ $name>](state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+                unsafe {
+                    let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+                    this.[<write_ $type_name>](lua::Lchecknumber(state, 2) as _);
+                    Ok(0)
+                }
+            }
+        }
+    };
+}
+
+pub struct Buffer(Vec<u8>, usize);
+
+impl Buffer {
+    fn new(size: usize) -> Self {
+        Self(Vec::with_capacity(size), 0)
+    }
+
+    fn read(&mut self, bytes: usize) -> Option<&[u8]> {
+        if bytes == 0 || self.0.len() == 0 {
+            return None;
+        }
+        let pos = self.1.min(self.0.len());
+        let bytes_to_read = if bytes + pos > self.0.len() {
+            bytes - (bytes + pos - self.0.len())
+        } else {
+            bytes
+        };
+        if bytes_to_read == 0 {
+            return None;
+        }
+        self.1 += bytes_to_read;
+        Some(&self.0[pos..pos + bytes_to_read])
+    }
+
+    // Straightforward ripoff from Cursor.
+    fn write(&mut self, data: &[u8]) {
+        if self.1 > self.0.len() {
+            return;
+        }
+        let len = self.0.len();
+        if len < self.1 {
+            self.0.resize(self.1, 0);
+        }
+        {
+            let space = self.0.len() - self.1;
+            let (left, right) = data.split_at(std::cmp::min(space, data.len()));
+            self.0[self.1..self.1 + left.len()].copy_from_slice(left);
+            self.0.extend_from_slice(right);
+        }
+        self.1 += data.len();
+    }
+
+    fn read_f32(&mut self) -> Option<f32> {
+        if self.0.len() == 0 || self.1 + 4 > self.0.len() {
+            return None;
+        }
+        let data = self.read(4)?;
+        unsafe {
+            Some(f32::from_bits(u32::from_le(
+                *std::mem::transmute::<_, &u32>(data.as_ptr()),
+            )))
+        }
+    }
+
+    fn write_f32(&mut self, value: f32) {
+        self.write(&value.to_le_bytes());
+    }
+
+    fn read_f64(&mut self) -> Option<f64> {
+        if self.0.len() == 0 || self.1 + 8 > self.0.len() {
+            return None;
+        }
+        let data = self.read(8)?;
+        unsafe {
+            Some(f64::from_bits(u64::from_le(
+                *std::mem::transmute::<_, &u64>(data.as_ptr()),
+            )))
+        }
+    }
+
+    fn write_f64(&mut self, value: f64) {
+        self.write(&value.to_le_bytes());
+    }
+
+    def_rw!(u8 u16 i16 u32 i32);
+
+    fn __gc(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let _ = lua::Lcheckudata(state, 1, lua::cstr!("cslb"))
+                .cast::<Self>()
+                .read();
+            Ok(0)
+        }
+    }
+
+    fn lm_read(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            match this.read(lua::Lcheckinteger(state, 2) as _) {
+                Some(val) => {
+                    lua::pushlstring(state, val.as_ptr(), val.len());
+                }
+                None => lua::pushnil(state),
+            }
+            Ok(1)
+        }
+    }
+
+    fn lm_write(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            this.write(check_slice!(state, 2));
+            Ok(0)
+        }
+    }
+
+    fn lm_read_bool(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            match this.read_u8() {
+                Some(val) => {
+                    lua::pushboolean(state, val as _);
+                }
+                None => lua::pushnil(state),
+            }
+            Ok(1)
+        }
+    }
+
+    fn lm_write_bool(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            this.write_u8(lua::toboolean(state, 2) as _);
+            Ok(0)
+        }
+    }
+
+    def_lmint!(byte, u8);
+    def_lmint!(ushort, u16);
+    def_lmint!(short, i16);
+    def_lmint!(ulong, u32);
+    def_lmint!(long, i32);
+    def_lmfloat!(float, f32);
+    def_lmfloat!(double, f64);
+
+    fn lm_tell(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            lua::pushinteger(state, this.1 as _);
+            Ok(1)
+        }
+    }
+
+    fn lm_seek(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            this.1 = (lua::Lcheckinteger(state, 2).max(0) as usize).min(this.0.len() - 1);
+            Ok(0)
+        }
+    }
+
+    fn lm_clear(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            this.0.clear();
+            this.1 = 0;
+            Ok(0)
+        }
+    }
+
+    fn lm_resize(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            let size = lua::Lcheckinteger(state, 2).max(0) as usize;
+            this.0.resize(size, 0);
+            this.1 = this.1.min(size);
+            Ok(0)
+        }
+    }
+
+    fn lm_shrink(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            this.0.shrink_to_fit();
+            Ok(1)
+        }
+    }
+
+    fn lm_get_value(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            lua::pushlstring(state, this.0.as_ptr(), this.0.len());
+            Ok(1)
+        }
+    }
+
+    fn lm_set_value(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("cslb")).cast::<Self>();
+            let data = check_slice!(state, 2);
+            this.0.clear();
+            this.1 = 0;
+            this.0.extend_from_slice(data);
+            Ok(0)
+        }
+    }
+
+    fn metatable(state: lua_State) {
+        unsafe {
+            if lua::Lnewmetatable(state, lua::cstr!("cslb")) {
+                lua::pushvalue(state, -1);
+                lua::setfield(state, -2, lua::cstr!("__index"));
+                insert_function!(state, "__gc", Self::__gc);
+                insert_function!(state, "Read", Self::lm_read);
+                insert_function!(state, "ReadBool", Self::lm_read_bool);
+                insert_function!(state, "ReadByte", Self::lm_read_byte);
+                insert_function!(state, "ReadUShort", Self::lm_read_ushort);
+                insert_function!(state, "ReadShort", Self::lm_read_short);
+                insert_function!(state, "ReadULong", Self::lm_read_ulong);
+                insert_function!(state, "ReadLong", Self::lm_read_long);
+                insert_function!(state, "ReadFloat", Self::lm_read_float);
+                insert_function!(state, "ReadDouble", Self::lm_read_double);
+
+                insert_function!(state, "Write", Self::lm_write);
+                insert_function!(state, "WriteBool", Self::lm_write_bool);
+                insert_function!(state, "WriteByte", Self::lm_write_byte);
+                insert_function!(state, "WriteUShort", Self::lm_write_ushort);
+                insert_function!(state, "WriteShort", Self::lm_write_short);
+                insert_function!(state, "WriteULong", Self::lm_write_ulong);
+                insert_function!(state, "WriteLong", Self::lm_write_long);
+                insert_function!(state, "WriteFloat", Self::lm_write_float);
+                insert_function!(state, "WriteDouble", Self::lm_write_double);
+
+                insert_function!(state, "Tell", Self::lm_tell);
+                insert_function!(state, "Seek", Self::lm_seek);
+                insert_function!(state, "Clear", Self::lm_clear);
+                insert_function!(state, "Resize", Self::lm_resize);
+                insert_function!(state, "Shrink", Self::lm_shrink);
+
+                insert_function!(state, "GetValue", Self::lm_get_value);
+                insert_function!(state, "SetValue", Self::lm_set_value);
+            }
+        }
+    }
+
+    pub fn l_new(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
+        unsafe {
+            let buffer = match lua::get_type(state, 1) {
+                3 => Self::new(lua::tonumber(state, 1) as _),
+                4 => {
+                    let data = check_slice!(state, 1);
+                    let mut buffer = Self::new(data.len());
+                    buffer.0.extend_from_slice(data);
+                    buffer
+                },
+                _ => {Self::new(0)}
+            };
+            let udata = lua::newuserdata(state, std::mem::size_of::<Self>()).cast::<Self>();
+            udata.write(buffer);
+            Self::metatable(state);
+            lua::setmetatable(state, -2);
+        }
+        Ok(1)
+    }
+}

+ 17 - 30
src/ldb.rs

@@ -4,7 +4,7 @@ use std::ptr::null;
 use lua_shared as lua;
 use lua_shared::lua_State;
 
-use crate::check_slice;
+use crate::{check_slice, insert_function};
 use crate::ltree::LTree;
 
 #[derive(Debug, Clone)]
@@ -28,7 +28,7 @@ impl LDb {
             let db = sled::open(std::str::from_utf8_unchecked(check_slice!(state, 1)))?;
             let ldb = lua::newuserdata(state, std::mem::size_of::<Self>()).cast::<Self>();
             ldb.write(Self(db));
-            Self::metatble(state);
+            Self::metatable(state);
             lua::setmetatable(state, -2);
         }
         Ok(1)
@@ -141,7 +141,7 @@ impl LDb {
             let tree = this.open_tree(std::str::from_utf8_unchecked(check_slice!(state, 2)))?;
             let ltree = lua::newuserdata(state, std::mem::size_of::<LTree>()).cast::<LTree>();
             ltree.write(LTree(tree));
-            LTree::metatble(state);
+            LTree::metatable(state);
             lua::setmetatable(state, -2);
             Ok(1)
         }
@@ -199,37 +199,24 @@ impl LDb {
         }
     }
 
-    fn metatble(state: lua_State) {
+    fn metatable(state: lua_State) {
         unsafe {
             if lua::Lnewmetatable(state, lua::cstr!("csldb")) {
                 lua::pushvalue(state, -1);
                 lua::setfield(state, -2, lua::cstr!("__index"));
-                lua::pushfunction(state, Self::__gc);
-                lua::setfield(state, -2, lua::cstr!("__gc"));
-                lua::pushfunction(state, Self::lm_name);
-                lua::setfield(state, -2, lua::cstr!("name"));
-                lua::pushfunction(state, Self::lm_clear);
-                lua::setfield(state, -2, lua::cstr!("clear"));
-                lua::pushfunction(state, Self::lm_get);
-                lua::setfield(state, -2, lua::cstr!("get"));
-                lua::pushfunction(state, Self::lm_insert);
-                lua::setfield(state, -2, lua::cstr!("insert"));
-                lua::pushfunction(state, Self::lm_remove);
-                lua::setfield(state, -2, lua::cstr!("remove"));
-                lua::pushfunction(state, Self::lm_range);
-                lua::setfield(state, -2, lua::cstr!("range"));
-                lua::pushfunction(state, Self::lm_scan_prefix);
-                lua::setfield(state, -2, lua::cstr!("scan_prefix"));
-                lua::pushfunction(state, Self::lm_tree_names);
-                lua::setfield(state, -2, lua::cstr!("tree_names"));
-                lua::pushfunction(state, Self::lm_open_tree);
-                lua::setfield(state, -2, lua::cstr!("open_tree"));
-                lua::pushfunction(state, Self::lm_generate_id);
-                lua::setfield(state, -2, lua::cstr!("generate_id"));
-                lua::pushfunction(state, Self::lm_export);
-                lua::setfield(state, -2, lua::cstr!("export"));
-                lua::pushfunction(state, Self::lm_import);
-                lua::setfield(state, -2, lua::cstr!("import"));
+                insert_function!(state, "__gc", Self::__gc);
+                insert_function!(state, "Name", Self::lm_name);
+                insert_function!(state, "Clear", Self::lm_clear);
+                insert_function!(state, "Get", Self::lm_get);
+                insert_function!(state, "Insert", Self::lm_insert);
+                insert_function!(state, "Remove", Self::lm_remove);
+                insert_function!(state, "Range", Self::lm_range);
+                insert_function!(state, "ScanPrefix", Self::lm_scan_prefix);
+                insert_function!(state, "TreeNames", Self::lm_tree_names);
+                insert_function!(state, "OpenTree", Self::lm_open_tree);
+                insert_function!(state, "GenerateID", Self::lm_generate_id);
+                insert_function!(state, "Export", Self::lm_export);
+                insert_function!(state, "Import", Self::lm_import);
             }
         }
     }

+ 12 - 2
src/lib.rs

@@ -1,9 +1,11 @@
 // use std::{collections::HashMap, hash::Hash};
 
 use ldb::LDb;
+use buffer::Buffer;
 use lua_shared as lua;
 use lua_shared::lua_State;
 
+mod buffer;
 mod ldb;
 mod ltree;
 
@@ -16,11 +18,19 @@ macro_rules! check_slice {
     }};
 }
 
+#[macro_export]
+macro_rules! insert_function {
+    ($state:ident, $name:expr, $func:expr) => {
+        lua_shared::pushfunction($state, $func);
+        lua_shared::setfield($state, -2, lua::cstr!($name));
+    };
+}
+
 #[no_mangle]
 unsafe extern "C" fn gmod13_open(state: lua_State) -> i32 {
     lua::createtable(state, 0, 1);
-    lua::pushfunction(state, LDb::l_open);
-    lua::setfield(state, -2, lua::cstr!("open"));
+    insert_function!(state, "Open", LDb::l_open);
+    insert_function!(state, "Buffer", Buffer::l_new);
     lua::pushstring(state, lua::cstr!("Sled 0.34.7"));
     lua::setfield(state, -2, lua::cstr!("_VERSION"));
     lua::setfield(state, lua::GLOBALSINDEX, lua::cstr!("sled"));

+ 10 - 18
src/ltree.rs

@@ -4,7 +4,7 @@ use std::ptr::null;
 use lua_shared as lua;
 use lua_shared::lua_State;
 
-use crate::check_slice;
+use crate::{check_slice, insert_function};
 
 #[derive(Debug, Clone)]
 pub struct LTree(pub sled::Tree);
@@ -116,27 +116,19 @@ impl LTree {
         }
     }
 
-    pub fn metatble(state: lua_State) {
+    pub fn metatable(state: lua_State) {
         unsafe {
             if lua::Lnewmetatable(state, lua::cstr!("cslt")) {
                 lua::pushvalue(state, -1);
                 lua::setfield(state, -2, lua::cstr!("__index"));
-                lua::pushfunction(state, Self::__gc);
-                lua::setfield(state, -2, lua::cstr!("__gc"));
-                lua::pushfunction(state, Self::lm_name);
-                lua::setfield(state, -2, lua::cstr!("name"));
-                lua::pushfunction(state, Self::lm_clear);
-                lua::setfield(state, -2, lua::cstr!("clear"));
-                lua::pushfunction(state, Self::lm_get);
-                lua::setfield(state, -2, lua::cstr!("get"));
-                lua::pushfunction(state, Self::lm_insert);
-                lua::setfield(state, -2, lua::cstr!("insert"));
-                lua::pushfunction(state, Self::lm_remove);
-                lua::setfield(state, -2, lua::cstr!("remove"));
-                lua::pushfunction(state, Self::lm_range);
-                lua::setfield(state, -2, lua::cstr!("range"));
-                lua::pushfunction(state, Self::lm_scan_prefix);
-                lua::setfield(state, -2, lua::cstr!("scan_prefix"));
+                insert_function!(state, "__gc", Self::__gc);
+                insert_function!(state, "Name", Self::lm_name);
+                insert_function!(state, "Clear", Self::lm_clear);
+                insert_function!(state, "Get", Self::lm_get);
+                insert_function!(state, "Insert", Self::lm_insert);
+                insert_function!(state, "Remove", Self::lm_remove);
+                insert_function!(state, "Range", Self::lm_range);
+                insert_function!(state, "ScanPrefix", Self::lm_scan_prefix);
             }
         }
     }