├── .gitignore ├── src ├── lib.rs └── plugin.rs ├── Cargo.toml └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /.idea 3 | /target 4 | **/*.rs.bk 5 | Cargo.lock 6 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate samp_sdk; 2 | extern crate memcache; 3 | 4 | mod plugin; 5 | use plugin::Memcached; 6 | 7 | new_plugin!(Memcached); -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "samp-plugin" 3 | version = "0.1.0" 4 | authors = ["ZOTTCE "] 5 | 6 | [lib] 7 | name = "plugin" 8 | crate-type = ["dylib"] 9 | 10 | [dependencies] 11 | samp-sdk = "0.8.1" 12 | memcache = "0.7" -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # SA:MP Plugin Example 2 | There is a simple Memcached plugin showing how to use samp-sdk in Rust. 3 | 4 | ## Include file 5 | ```C 6 | native Memcached_Connect(const address[]); 7 | native Memcached_Get(connection, const key[], &value); 8 | native Memcached_GetString(connection, const key[], value[], size=sizeof(value)); 9 | native Memcached_Set(connection, const key[], value, expire); 10 | native Memcached_SetString(connection, const key[], const value[], expire); 11 | native Memcached_Delete(connection, const key[]); 12 | native Memcached_Increment(connection, const key[], value); 13 | ``` 14 | 15 | ## Pawn example 16 | ```C 17 | main() { 18 | new con = Memcached_Connect("memcache://localhost:11211"); 19 | 20 | Memcached_Set(con, "foo", 228, 0); 21 | 22 | new value = 0; 23 | new string[256]; 24 | 25 | if (Memcached_Get(con, "foo", value)) { 26 | printf("%d", value); 27 | } else { 28 | printf("cannot get a value"); 29 | } 30 | 31 | Memcached_Delete(con, "foo"); 32 | Memcached_Set(con, "foo", 1, 0); 33 | Memcached_Increment(con, "foo", 5); 34 | Memcached_Get(con, "foo", value); 35 | Memcached_SetString(con, "string", "some value", 0); 36 | Memcached_GetString(con, "string", string); 37 | 38 | printf("%d %s", value, string); 39 | } 40 | ``` -------------------------------------------------------------------------------- /src/plugin.rs: -------------------------------------------------------------------------------- 1 | use samp_sdk::consts::*; 2 | use samp_sdk::types::Cell; 3 | use samp_sdk::amx::{AmxResult, AMX}; 4 | 5 | use memcache::Client; 6 | 7 | define_native!(connect, address: String); 8 | define_native!(get, connection: usize, key: String, value: ref Cell); 9 | define_native!(get_string, connection: usize, key: String, value: ref Cell, size: usize); 10 | define_native!(set, connection: usize, key: String, value: Cell, expire: u32); 11 | define_native!(set_string, connection: usize, key: String, value: String, expire: u32); 12 | define_native!(delete, connection: usize, key: String); 13 | define_native!(increment, connection: usize, key: String, value: Cell); 14 | 15 | pub struct Memcached { 16 | clients: Vec, 17 | } 18 | 19 | impl Memcached { 20 | pub fn load(&self) -> bool { 21 | return true; 22 | } 23 | 24 | pub fn unload(&self) { 25 | 26 | } 27 | 28 | pub fn amx_load(&mut self, amx: &mut AMX) -> Cell { 29 | let natives = natives!{ 30 | "Memcached_Connect" => connect, 31 | "Memcached_Set" => set, 32 | "Memcached_SetString" => set_string, 33 | "Memcached_Get" => get, 34 | "Memcached_GetString" => get_string, 35 | "Memcached_Delete" => delete, 36 | "Memcached_Increment" => increment 37 | }; 38 | 39 | match amx.register(&natives) { 40 | Ok(_) => log!("Natives are successful loaded"), 41 | Err(err) => log!("Whoops, there is an error {:?}", err), 42 | } 43 | 44 | AMX_ERR_NONE 45 | } 46 | 47 | pub fn amx_unload(&self, _: &mut AMX) -> Cell { 48 | AMX_ERR_NONE 49 | } 50 | 51 | pub fn connect(&mut self, _: &AMX, address: String) -> AmxResult { 52 | match Client::new(address.as_str()) { 53 | Ok(client) => { 54 | self.clients.push(client); 55 | Ok(self.clients.len() as Cell - 1) 56 | }, 57 | Err(_) => Ok(-1), 58 | } 59 | } 60 | 61 | pub fn get(&mut self, _: &AMX, con: usize, key: String, value: &mut Cell) -> AmxResult { 62 | if con < self.clients.len() { 63 | match self.clients[con].get::(key.as_str()) { 64 | Ok(Some(data)) => { 65 | *value = data; 66 | Ok(1) 67 | }, 68 | Ok(None) => Ok(0), 69 | Err(_) => Ok(-1) 70 | } 71 | } else { 72 | Ok(-2) 73 | } 74 | } 75 | 76 | pub fn get_string(&mut self, _: &AMX, con: usize, key: String, string: &mut Cell, size: usize) 77 | -> AmxResult { 78 | if con < self.clients.len() { 79 | match self.clients[con].get::(key.as_str()) { 80 | Ok(Some(data)) => { 81 | let encoded = samp_sdk::cp1251::encode(&data)?; 82 | set_string!(encoded, string, size); 83 | Ok(1) 84 | }, 85 | Ok(None) => Ok(0), 86 | Err(_) => Ok(-1), 87 | } 88 | } else { 89 | Ok(-2) 90 | } 91 | } 92 | 93 | pub fn set(&mut self, _: &AMX, con: usize, key: String, value: Cell, expire: u32) 94 | -> AmxResult { 95 | if con < self.clients.len() { 96 | match self.clients[con].set(key.as_str(), value, expire) { 97 | Ok(_) => Ok(1), 98 | Err(_) => Ok(-1) 99 | } 100 | } else { 101 | Ok(-2) 102 | } 103 | } 104 | 105 | pub fn set_string(&mut self, _: &AMX, con: usize, key: String, value: String, expire: u32) 106 | -> AmxResult { 107 | if con < self.clients.len() { 108 | match self.clients[con].set(key.as_str(), value.as_str(), expire) { 109 | Ok(_) => Ok(1), 110 | Err(_) => Ok(-1), 111 | } 112 | } else { 113 | Ok(-2) 114 | } 115 | } 116 | 117 | pub fn increment(&mut self, _: &AMX, con: usize, key: String, value: Cell) 118 | -> AmxResult { 119 | if con < self.clients.len() { 120 | match self.clients[con].increment(key.as_str(), value as u64) { 121 | Ok(_) => Ok(1), 122 | Err(_) => Ok(-1), 123 | } 124 | } else { 125 | Ok(-2) 126 | } 127 | } 128 | 129 | pub fn delete(&mut self, _: &AMX, con: usize, key: String) -> AmxResult { 130 | if con < self.clients.len() { 131 | match self.clients[con].delete(key.as_str()) { 132 | Ok(true) => Ok(1), 133 | Ok(false) => Ok(0), 134 | Err(_) => Ok(-1), 135 | } 136 | } else { 137 | Ok(-2) 138 | } 139 | } 140 | } 141 | 142 | impl Default for Memcached { 143 | fn default() -> Self { 144 | Memcached { 145 | clients: Vec::new(), 146 | } 147 | } 148 | } --------------------------------------------------------------------------------