ldb.rs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. use std::ops::{Deref, DerefMut};
  2. use std::ptr::null;
  3. use lua_shared as lua;
  4. use lua_shared::lua_State;
  5. use crate::check_slice;
  6. use crate::ltree::LTree;
  7. #[derive(Debug, Clone)]
  8. pub struct LDb(pub sled::Db);
  9. impl Deref for LDb {
  10. type Target = sled::Db;
  11. fn deref(&self) -> &Self::Target {
  12. &self.0
  13. }
  14. }
  15. impl DerefMut for LDb {
  16. fn deref_mut(&mut self) -> &mut sled::Db {
  17. &mut self.0
  18. }
  19. }
  20. impl LDb {
  21. pub fn l_open(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  22. unsafe {
  23. let db = sled::open(std::str::from_utf8_unchecked(check_slice!(state, 1)))?;
  24. let ldb = lua::newuserdata(state, std::mem::size_of::<Self>()).cast::<Self>();
  25. ldb.write(Self(db));
  26. Self::metatble(state);
  27. lua::setmetatable(state, -2);
  28. }
  29. Ok(1)
  30. }
  31. fn lm_name(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  32. unsafe {
  33. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  34. let name = this.name();
  35. lua::pushlstring(state, name.as_ptr(), name.len());
  36. Ok(1)
  37. }
  38. }
  39. fn lm_clear(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  40. unsafe {
  41. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  42. this.clear()?;
  43. Ok(0)
  44. }
  45. }
  46. fn lm_get(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  47. unsafe {
  48. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  49. if let Some(ivec) = this.0.get(check_slice!(state, 2))? {
  50. lua::pushlstring(state, ivec.as_ptr(), ivec.len());
  51. } else {
  52. lua::pushnil(state)
  53. }
  54. Ok(1)
  55. }
  56. }
  57. fn lm_insert(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  58. unsafe {
  59. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  60. this.insert(check_slice!(state, 2), check_slice!(state, 3))?;
  61. Ok(0)
  62. }
  63. }
  64. fn lm_remove(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  65. unsafe {
  66. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  67. this.remove(check_slice!(state, 2))?;
  68. Ok(0)
  69. }
  70. }
  71. fn lm_range(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  72. unsafe {
  73. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  74. let mut range = this.range(check_slice!(state, 2)..=check_slice!(state, 3));
  75. lua::pushfunction(state, move |state| {
  76. if let Some(tree_name) = range.next() {
  77. let (key, value) = tree_name?;
  78. lua::pushlstring(state, key.as_ptr(), key.len());
  79. lua::pushlstring(state, value.as_ptr(), value.len());
  80. Ok(2)
  81. } else {
  82. Ok(0)
  83. }
  84. });
  85. Ok(1)
  86. }
  87. }
  88. fn lm_scan_prefix(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  89. unsafe {
  90. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  91. let prefix = {
  92. let mut len = 0;
  93. std::slice::from_raw_parts(lua::Loptlstring(state, 2, null(), &mut len), len)
  94. };
  95. let mut prefix = this.scan_prefix(prefix);
  96. lua::pushfunction(state, move |state| {
  97. if let Some(tree_name) = prefix.next() {
  98. let (key, value) = tree_name?;
  99. lua::pushlstring(state, key.as_ptr(), key.len());
  100. lua::pushlstring(state, value.as_ptr(), value.len());
  101. Ok(2)
  102. } else {
  103. Ok(0)
  104. }
  105. });
  106. Ok(1)
  107. }
  108. }
  109. fn lm_tree_names(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  110. unsafe {
  111. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  112. let mut iter = this.0.tree_names().into_iter();
  113. lua::pushfunction(state, move |state| {
  114. if let Some(tree_name) = iter.next() {
  115. lua::pushlstring(state, tree_name.as_ptr(), tree_name.len());
  116. Ok(1)
  117. } else {
  118. Ok(0)
  119. }
  120. });
  121. Ok(1)
  122. }
  123. }
  124. fn lm_open_tree(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  125. unsafe {
  126. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  127. let tree = this.open_tree(std::str::from_utf8_unchecked(check_slice!(state, 2)))?;
  128. let ltree = lua::newuserdata(state, std::mem::size_of::<LTree>()).cast::<LTree>();
  129. ltree.write(LTree(tree));
  130. LTree::metatble(state);
  131. lua::setmetatable(state, -2);
  132. Ok(1)
  133. }
  134. }
  135. fn lm_generate_id(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  136. unsafe {
  137. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  138. lua::pushnumber(state, this.generate_id()? as _);
  139. Ok(1)
  140. }
  141. }
  142. fn lm_export(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  143. unsafe {
  144. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  145. let export: Vec<(Vec<u8>, Vec<u8>, Vec<Vec<Vec<u8>>>)> = this
  146. .export()
  147. .into_iter()
  148. .map(|(collection, name, kv)| {
  149. (
  150. collection,
  151. name,
  152. kv.into_iter().collect::<Vec<Vec<Vec<u8>>>>(),
  153. )
  154. })
  155. .collect();
  156. let blob = bincode::serialize(&export)?;
  157. lua::pushlstring(state, blob.as_ptr(), blob.len());
  158. Ok(1)
  159. }
  160. }
  161. fn lm_import(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  162. unsafe {
  163. let this = &mut *lua::Lcheckudata(state, 1, lua::cstr!("csldb")).cast::<Self>();
  164. let blob = check_slice!(state, 2);
  165. let import: Vec<(Vec<u8>, Vec<u8>, Vec<Vec<Vec<u8>>>)> = bincode::deserialize(blob)?;
  166. this.import(
  167. import
  168. .into_iter()
  169. .map(|(collection, name, kv)| (collection, name, kv.into_iter()))
  170. .collect(),
  171. );
  172. Ok(0)
  173. }
  174. }
  175. fn __gc(state: lua_State) -> Result<i32, Box<dyn std::error::Error>> {
  176. unsafe {
  177. let _ = lua::Lcheckudata(state, 1, lua::cstr!("csldb"))
  178. .cast::<Self>()
  179. .read();
  180. Ok(0)
  181. }
  182. }
  183. fn metatble(state: lua_State) {
  184. unsafe {
  185. if lua::Lnewmetatable(state, lua::cstr!("csldb")) {
  186. lua::pushvalue(state, -1);
  187. lua::setfield(state, -2, lua::cstr!("__index"));
  188. lua::pushfunction(state, Self::__gc);
  189. lua::setfield(state, -2, lua::cstr!("__gc"));
  190. lua::pushfunction(state, Self::lm_name);
  191. lua::setfield(state, -2, lua::cstr!("name"));
  192. lua::pushfunction(state, Self::lm_clear);
  193. lua::setfield(state, -2, lua::cstr!("clear"));
  194. lua::pushfunction(state, Self::lm_get);
  195. lua::setfield(state, -2, lua::cstr!("get"));
  196. lua::pushfunction(state, Self::lm_insert);
  197. lua::setfield(state, -2, lua::cstr!("insert"));
  198. lua::pushfunction(state, Self::lm_remove);
  199. lua::setfield(state, -2, lua::cstr!("remove"));
  200. lua::pushfunction(state, Self::lm_range);
  201. lua::setfield(state, -2, lua::cstr!("range"));
  202. lua::pushfunction(state, Self::lm_scan_prefix);
  203. lua::setfield(state, -2, lua::cstr!("scan_prefix"));
  204. lua::pushfunction(state, Self::lm_tree_names);
  205. lua::setfield(state, -2, lua::cstr!("tree_names"));
  206. lua::pushfunction(state, Self::lm_open_tree);
  207. lua::setfield(state, -2, lua::cstr!("open_tree"));
  208. lua::pushfunction(state, Self::lm_generate_id);
  209. lua::setfield(state, -2, lua::cstr!("generate_id"));
  210. lua::pushfunction(state, Self::lm_export);
  211. lua::setfield(state, -2, lua::cstr!("export"));
  212. lua::pushfunction(state, Self::lm_import);
  213. lua::setfield(state, -2, lua::cstr!("import"));
  214. }
  215. }
  216. }
  217. }