#[derive(Debug, Clone, PartialEq)]
pub enum RedisValue {
Nil,
Int(i64),
Float(f64),
String(String),
Bytes(Vec<u8>),
Array(Vec<RedisValue>),
Bool(bool),
}
impl RedisValue {
pub fn as_string(&self) -> Option<String> {
match self {
RedisValue::String(s) => Some(s.clone()),
_ => None,
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
RedisValue::Int(i) => Some(*i),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
RedisValue::Float(f) => Some(*f),
_ => None,
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
RedisValue::Bool(b) => Some(*b),
_ => None,
}
}
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
RedisValue::Bytes(b) => Some(b.as_slice()),
_ => None,
}
}
pub fn as_array(&self) -> Option<&[RedisValue]> {
match self {
RedisValue::Array(arr) => Some(arr.as_slice()),
_ => None,
}
}
pub fn is_nil(&self) -> bool {
matches!(self, RedisValue::Nil)
}
}
impl From<String> for RedisValue {
fn from(s: String) -> Self {
RedisValue::String(s)
}
}
impl From<&str> for RedisValue {
fn from(s: &str) -> Self {
RedisValue::String(s.to_string())
}
}
impl From<i64> for RedisValue {
fn from(i: i64) -> Self {
RedisValue::Int(i)
}
}
impl From<i32> for RedisValue {
fn from(i: i32) -> Self {
RedisValue::Int(i as i64)
}
}
impl From<f64> for RedisValue {
fn from(f: f64) -> Self {
RedisValue::Float(f)
}
}
impl From<bool> for RedisValue {
fn from(b: bool) -> Self {
RedisValue::Bool(b)
}
}
impl From<Vec<u8>> for RedisValue {
fn from(bytes: Vec<u8>) -> Self {
RedisValue::Bytes(bytes)
}
}
impl From<redis::Value> for RedisValue {
fn from(value: redis::Value) -> Self {
match value {
redis::Value::Nil => RedisValue::Nil,
redis::Value::Int(i) => RedisValue::Int(i),
redis::Value::BulkString(bytes) => {
match String::from_utf8(bytes.clone()) {
Ok(s) => RedisValue::String(s),
Err(_) => RedisValue::Bytes(bytes),
}
}
redis::Value::Array(values) => {
RedisValue::Array(values.into_iter().map(RedisValue::from).collect())
}
redis::Value::SimpleString(s) => RedisValue::String(s),
redis::Value::Okay => RedisValue::Bool(true),
redis::Value::Map(_) => {
RedisValue::String(format!("{:?}", value))
}
redis::Value::Attribute { .. } => {
RedisValue::String(format!("{:?}", value))
}
redis::Value::Set(_) => {
RedisValue::String(format!("{:?}", value))
}
redis::Value::Double(f) => RedisValue::Float(f),
redis::Value::Boolean(b) => RedisValue::Bool(b),
redis::Value::VerbatimString { .. } => {
RedisValue::String(format!("{:?}", value))
}
redis::Value::BigNumber(_) => {
RedisValue::String(format!("{:?}", value))
}
redis::Value::Push { .. } => {
RedisValue::String(format!("{:?}", value))
}
_ => RedisValue::String(format!("{:?}", value)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_redis_value_nil() {
let value = RedisValue::Nil;
assert!(value.is_nil());
assert_eq!(value.as_string(), None);
assert_eq!(value.as_i64(), None);
}
#[test]
fn test_redis_value_int() {
let value = RedisValue::Int(42);
assert!(!value.is_nil());
assert_eq!(value.as_i64(), Some(42));
assert_eq!(value.as_string(), None);
}
#[test]
fn test_redis_value_float() {
let value = RedisValue::Float(123.456);
assert_eq!(value.as_f64(), Some(123.456));
assert_eq!(value.as_i64(), None);
}
#[test]
fn test_redis_value_string() {
let value = RedisValue::String("hello".to_string());
assert_eq!(value.as_string(), Some("hello".to_string()));
assert_eq!(value.as_i64(), None);
}
#[test]
fn test_redis_value_bool() {
let value = RedisValue::Bool(true);
assert_eq!(value.as_bool(), Some(true));
assert_eq!(value.as_string(), None);
}
#[test]
fn test_redis_value_bytes() {
let bytes = vec![1, 2, 3, 4];
let value = RedisValue::Bytes(bytes.clone());
assert_eq!(value.as_bytes(), Some(bytes.as_slice()));
assert_eq!(value.as_string(), None);
}
#[test]
fn test_redis_value_array() {
let arr = vec![
RedisValue::Int(1),
RedisValue::String("test".to_string()),
RedisValue::Nil,
];
let value = RedisValue::Array(arr.clone());
assert_eq!(value.as_array(), Some(arr.as_slice()));
assert_eq!(value.as_string(), None);
}
#[test]
fn test_from_string() {
let value: RedisValue = "hello".into();
assert_eq!(value, RedisValue::String("hello".to_string()));
let value: RedisValue = String::from("world").into();
assert_eq!(value, RedisValue::String("world".to_string()));
}
#[test]
fn test_from_int() {
let value: RedisValue = 42i64.into();
assert_eq!(value, RedisValue::Int(42));
let value: RedisValue = 100i32.into();
assert_eq!(value, RedisValue::Int(100));
}
#[test]
fn test_from_float() {
let value: RedisValue = 123.456f64.into();
assert_eq!(value, RedisValue::Float(123.456));
}
#[test]
fn test_from_bool() {
let value: RedisValue = true.into();
assert_eq!(value, RedisValue::Bool(true));
let value: RedisValue = false.into();
assert_eq!(value, RedisValue::Bool(false));
}
#[test]
fn test_from_bytes() {
let bytes = vec![1, 2, 3];
let value: RedisValue = bytes.clone().into();
assert_eq!(value, RedisValue::Bytes(bytes));
}
#[test]
fn test_from_redis_value_nil() {
let redis_val = redis::Value::Nil;
let value: RedisValue = redis_val.into();
assert_eq!(value, RedisValue::Nil);
}
#[test]
fn test_from_redis_value_int() {
let redis_val = redis::Value::Int(42);
let value: RedisValue = redis_val.into();
assert_eq!(value, RedisValue::Int(42));
}
#[test]
fn test_from_redis_value_data_utf8() {
let redis_val = redis::Value::BulkString(b"hello".to_vec());
let value: RedisValue = redis_val.into();
assert_eq!(value, RedisValue::String("hello".to_string()));
}
#[test]
fn test_from_redis_value_data_binary() {
let bytes = vec![0xFF, 0xFE, 0xFD];
let redis_val = redis::Value::BulkString(bytes.clone());
let value: RedisValue = redis_val.into();
assert_eq!(value, RedisValue::Bytes(bytes));
}
#[test]
fn test_from_redis_value_bulk() {
let redis_val = redis::Value::Array(vec![
redis::Value::Int(1),
redis::Value::BulkString(b"test".to_vec()),
]);
let value: RedisValue = redis_val.into();
if let RedisValue::Array(arr) = value {
assert_eq!(arr.len(), 2);
assert_eq!(arr[0], RedisValue::Int(1));
assert_eq!(arr[1], RedisValue::String("test".to_string()));
} else {
panic!("Expected Array");
}
}
#[test]
fn test_from_redis_value_status() {
let redis_val = redis::Value::SimpleString("OK".to_string());
let value: RedisValue = redis_val.into();
assert_eq!(value, RedisValue::String("OK".to_string()));
}
#[test]
fn test_from_redis_value_okay() {
let redis_val = redis::Value::Okay;
let value: RedisValue = redis_val.into();
assert_eq!(value, RedisValue::Bool(true));
}
#[test]
fn test_clone() {
let value = RedisValue::String("test".to_string());
let cloned = value.clone();
assert_eq!(value, cloned);
}
#[test]
fn test_debug() {
let value = RedisValue::Int(42);
let debug_str = format!("{:?}", value);
assert!(debug_str.contains("Int"));
assert!(debug_str.contains("42"));
}
#[test]
fn test_partial_eq() {
assert_eq!(RedisValue::Nil, RedisValue::Nil);
assert_eq!(RedisValue::Int(42), RedisValue::Int(42));
assert_ne!(RedisValue::Int(42), RedisValue::Int(43));
assert_ne!(RedisValue::Int(42), RedisValue::String("42".to_string()));
}
}