Skip to content

Commit

Permalink
Add support to casting RedisResult to CString.
Browse files Browse the repository at this point in the history
  • Loading branch information
nihohit authored and shachlanAmazon committed Aug 18, 2022
1 parent 02fbee5 commit 043435e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
24 changes: 24 additions & 0 deletions redis/src/types.rs
Expand Up @@ -2,6 +2,7 @@ use std::collections::{BTreeMap, BTreeSet};
use std::convert::From;
use std::default::Default;
use std::error;
use std::ffi::{CString, NulError};
use std::fmt;
use std::hash::{BuildHasher, Hash};
use std::io;
Expand Down Expand Up @@ -265,6 +266,18 @@ impl From<Utf8Error> for RedisError {
}
}

impl From<NulError> for RedisError {
fn from(err: NulError) -> RedisError {
RedisError {
repr: ErrorRepr::WithDescriptionAndDetail(
ErrorKind::TypeError,
"Value contains interior nul terminator",
err.to_string(),
),
}
}
}

#[cfg(feature = "tls")]
impl From<native_tls::Error> for RedisError {
fn from(err: native_tls::Error) -> RedisError {
Expand Down Expand Up @@ -1147,6 +1160,17 @@ impl FromRedisValue for bool {
}
}

impl FromRedisValue for CString {
fn from_redis_value(v: &Value) -> RedisResult<CString> {
match *v {
Value::Data(ref bytes) => Ok(CString::new(bytes.clone())?),
Value::Okay => Ok(CString::new("OK")?),
Value::Status(ref val) => Ok(CString::new(val.as_bytes())?),
_ => invalid_type_error!(v, "Response type not CString compatible."),
}
}
}

impl FromRedisValue for String {
fn from_redis_value(v: &Value) -> RedisResult<String> {
match *v {
Expand Down
29 changes: 29 additions & 0 deletions redis/tests/test_types.rs
@@ -1,3 +1,5 @@
use std::ffi::CString;

#[test]
fn test_is_single_arg() {
use redis::ToRedisArgs;
Expand Down Expand Up @@ -193,6 +195,33 @@ fn test_bytes() {
assert_eq!(v.unwrap_err().kind(), ErrorKind::TypeError);
}

#[test]
fn test_cstring() {
use redis::{ErrorKind, FromRedisValue, RedisResult, Value};

let content: &[u8] = b"\x01\x02\x03\x04";
let content_vec: Vec<u8> = Vec::from(content);

let v: RedisResult<CString> = FromRedisValue::from_redis_value(&Value::Data(content_vec));
assert_eq!(v, Ok(CString::new(content).unwrap()));

let v: RedisResult<CString> =
FromRedisValue::from_redis_value(&Value::Status("garbage".into()));
assert_eq!(v, Ok(CString::new("garbage").unwrap()));

let v: RedisResult<CString> = FromRedisValue::from_redis_value(&Value::Okay);
assert_eq!(v, Ok(CString::new("OK").unwrap()));

let v: RedisResult<CString> = FromRedisValue::from_redis_value(&Value::Nil);
assert_eq!(v.unwrap_err().kind(), ErrorKind::TypeError);

let v: RedisResult<CString> = FromRedisValue::from_redis_value(&Value::Int(0));
assert_eq!(v.unwrap_err().kind(), ErrorKind::TypeError);

let v: RedisResult<CString> = FromRedisValue::from_redis_value(&Value::Int(42));
assert_eq!(v.unwrap_err().kind(), ErrorKind::TypeError);
}

#[test]
fn test_types_to_redis_args() {
use redis::ToRedisArgs;
Expand Down

0 comments on commit 043435e

Please sign in to comment.