Skip to content

Commit 4c6fc5a

Browse files
authored
Add support for hash_get/hash_set and Sring operations (#58)
* Add support for hash_get/hash_set * Add RedisString methods
1 parent 3524c3c commit 4c6fc5a

File tree

5 files changed

+72
-9
lines changed

5 files changed

+72
-9
lines changed

src/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,8 @@ impl Context {
176176
pub fn replicate_verbatim(&self) {
177177
raw::replicate_verbatim(self.ctx);
178178
}
179+
180+
pub fn create_string(&self, s: &str) -> RedisString{
181+
RedisString::create(self.ctx, s)
182+
}
179183
}

src/key.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use libc::size_t;
22
use std::convert::TryFrom;
33
use std::os::raw::c_void;
44
use std::ptr;
5-
use std::string;
5+
use std::str::Utf8Error;
66
use std::time::Duration;
77

88
use crate::from_byte_string;
@@ -74,6 +74,15 @@ impl RedisKey {
7474
};
7575
Ok(val)
7676
}
77+
78+
pub fn hash_get(&self, field: &str) -> Result<Option<RedisString>, RedisError> {
79+
let val = if self.is_null() {
80+
None
81+
} else {
82+
hash_get_key(self.ctx, self.key_inner, field)
83+
};
84+
Ok(val)
85+
}
7786
}
7887

7988
impl Drop for RedisKey {
@@ -130,6 +139,14 @@ impl RedisKeyWritable {
130139
Ok(Some(read_key(self.key_inner)?))
131140
}
132141

142+
pub fn hash_set(&self, field: &str, value: RedisString) -> raw::Status {
143+
raw::hash_set(self.key_inner, field, value.inner)
144+
}
145+
146+
pub fn hash_get(&self, field: &str) -> Result<Option<RedisString>, RedisError> {
147+
Ok(hash_get_key(self.ctx, self.key_inner, field))
148+
}
149+
133150
pub fn set_expire(&self, expire: Duration) -> RedisResult {
134151
let exp_millis = expire.as_millis();
135152

@@ -215,14 +232,23 @@ impl Drop for RedisKeyWritable {
215232
}
216233
}
217234

218-
fn read_key(key: *mut raw::RedisModuleKey) -> Result<String, string::FromUtf8Error> {
235+
fn read_key(key: *mut raw::RedisModuleKey) -> Result<String, Utf8Error> {
219236
let mut length: size_t = 0;
220237
from_byte_string(
221238
raw::string_dma(key, &mut length, raw::KeyMode::READ),
222239
length,
223240
)
224241
}
225242

243+
fn hash_get_key(ctx: *mut raw::RedisModuleCtx, key: *mut raw::RedisModuleKey, field: &str) -> Option<RedisString> {
244+
let res = raw::hash_get(key, field);
245+
if res.is_null() {
246+
None
247+
} else {
248+
Some(RedisString::new(ctx, res))
249+
}
250+
}
251+
226252
fn to_raw_mode(mode: KeyMode) -> raw::KeyMode {
227253
match mode {
228254
KeyMode::Read => raw::KeyMode::READ,

src/lib.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//#![allow(dead_code)]
22

33
use std::os::raw::c_char;
4-
use std::string;
4+
use std::str::Utf8Error;
55

66
#[macro_use]
77
extern crate bitflags;
@@ -40,15 +40,12 @@ pub enum LogLevel {
4040
Warning,
4141
}
4242

43-
fn from_byte_string(
44-
byte_str: *const c_char,
45-
length: size_t,
46-
) -> Result<String, string::FromUtf8Error> {
43+
fn from_byte_string(byte_str: *const c_char, length: size_t) -> Result<String, Utf8Error> {
4744
let mut vec_str: Vec<u8> = Vec::with_capacity(length as usize);
4845
for j in 0..length {
4946
let byte = unsafe { *byte_str.offset(j as isize) } as u8;
5047
vec_str.insert(j, byte);
5148
}
5249

53-
String::from_utf8(vec_str)
50+
String::from_utf8(vec_str).map_err(|e| e.utf8_error())
5451
}

src/raw.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern crate num_traits;
1111
use libc::size_t;
1212
use num_traits::FromPrimitive;
1313
use std::ffi::CString;
14+
use std::ptr;
1415
use std::slice;
1516

1617
pub use crate::redisraw::bindings::*;
@@ -235,6 +236,20 @@ pub fn string_dma(key: *mut RedisModuleKey, len: *mut size_t, mode: KeyMode) ->
235236
unsafe { RedisModule_StringDMA.unwrap()(key, len, mode.bits) }
236237
}
237238

239+
pub fn hash_get(key: *mut RedisModuleKey, field: &str) -> *mut RedisModuleString {
240+
let res: *mut RedisModuleString = ptr::null_mut();
241+
unsafe {
242+
RedisModule_HashGet.unwrap()(key, REDISMODULE_HASH_CFIELDS as i32, CString::new(field).unwrap().as_ptr(), &res, 0);
243+
}
244+
res
245+
}
246+
247+
pub fn hash_set(key: *mut RedisModuleKey, field: &str, value: *mut RedisModuleString) -> Status {
248+
unsafe {
249+
RedisModule_HashSet.unwrap()(key, REDISMODULE_HASH_CFIELDS as i32, CString::new(field).unwrap().as_ptr(), value, 0).into()
250+
}
251+
}
252+
238253
// Returns pointer to the C string, and sets len to its length
239254
pub fn string_ptr_len(s: *mut RedisModuleString, len: *mut size_t) -> *const c_char {
240255
unsafe { RedisModule_StringPtrLen.unwrap()(s, len) }
@@ -318,3 +333,7 @@ pub fn save_float(rdb: *mut RedisModuleIO, val: f32) {
318333
pub fn save_unsigned(rdb: *mut RedisModuleIO, val: u64) {
319334
unsafe { RedisModule_SaveUnsigned.unwrap()(rdb, val) };
320335
}
336+
337+
pub fn string_append_buffer(ctx: *mut RedisModuleCtx, s: *mut RedisModuleString, buff: &str) -> Status {
338+
unsafe { RedisModule_StringAppendBuffer.unwrap()(ctx, s, buff.as_ptr() as *mut i8, buff.len()).into() }
339+
}

src/redismodule.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,36 @@ pub struct RedisString {
7171
}
7272

7373
impl RedisString {
74+
pub fn new(ctx: *mut raw::RedisModuleCtx, inner: *mut raw::RedisModuleString) -> RedisString {
75+
RedisString{
76+
ctx,
77+
inner
78+
}
79+
}
80+
7481
pub fn create(ctx: *mut raw::RedisModuleCtx, s: &str) -> RedisString {
7582
let str = CString::new(s).unwrap();
7683
let inner = unsafe { raw::RedisModule_CreateString.unwrap()(ctx, str.as_ptr(), s.len()) };
7784

7885
RedisString { ctx, inner }
7986
}
8087

81-
pub fn from_ptr<'a>(ptr: *mut raw::RedisModuleString) -> Result<&'a str, str::Utf8Error> {
88+
pub fn from_ptr<'a>(ptr: *const raw::RedisModuleString) -> Result<&'a str, str::Utf8Error> {
8289
let mut len: libc::size_t = 0;
8390
let bytes = unsafe { raw::RedisModule_StringPtrLen.unwrap()(ptr, &mut len) };
8491

8592
str::from_utf8(unsafe { slice::from_raw_parts(bytes as *const u8, len) })
8693
}
94+
95+
pub fn append(&mut self, s: &str) -> raw::Status {
96+
raw::string_append_buffer(self.ctx, self.inner, s)
97+
}
98+
99+
pub fn len(&self) -> usize {
100+
let mut len: usize = 0;
101+
raw::string_ptr_len(self.inner, &mut len);
102+
len
103+
}
87104
}
88105

89106
impl Drop for RedisString {

0 commit comments

Comments
 (0)