use redis::Commands;
use redis_derive::{FromRedisValue, ToRedisArgs};
#[derive(FromRedisValue, ToRedisArgs, Debug, PartialEq)]
#[redis(rename_all = "snake_case")]
enum UserRole {
Administrator,
Moderator,
RegularUser,
GuestUser,
}
#[derive(FromRedisValue, ToRedisArgs, Debug, PartialEq)]
enum Status {
Active,
Inactive,
Pending,
}
fn main() -> redis::RedisResult<()> {
println!("🚀 Redis Derive Enum Branches Example");
println!("=====================================");
let client = redis::Client::open("redis://127.0.0.1:6379/")?;
let mut con = client.get_connection()?;
println!("\n1️⃣ Testing BulkString deserialization (normal case)");
test_bulk_string_case(&mut con)?;
println!("\n2️⃣ Testing SimpleString deserialization");
test_simple_string_case()?;
println!("\n3️⃣ Testing VerbatimString deserialization");
test_verbatim_string_case()?;
println!("\n4️⃣ Testing Nil value error handling");
test_nil_case()?;
println!("\n5️⃣ Testing invalid type error handling");
test_invalid_type_case()?;
println!("\n6️⃣ Testing invalid UTF-8 error handling");
test_invalid_utf8_case()?;
println!("\n7️⃣ Testing unknown variant error handling");
test_unknown_variant_case()?;
println!("\n✅ All enum deserialization branches tested successfully!");
Ok(())
}
fn test_bulk_string_case(con: &mut redis::Connection) -> redis::RedisResult<()> {
let role = UserRole::Administrator;
let _: () = con.set("user_role", &role)?;
let retrieved_role: UserRole = con.get("user_role")?;
println!(" ✓ Stored: {:?}", role);
println!(" ✓ Retrieved: {:?}", retrieved_role);
assert_eq!(role, retrieved_role);
println!(" ✓ BulkString deserialization works correctly");
Ok(())
}
fn test_simple_string_case() -> redis::RedisResult<()> {
let simple_string_value = redis::Value::SimpleString("moderator".to_string());
let result: redis::RedisResult<UserRole> = redis::FromRedisValue::from_redis_value(&simple_string_value);
match result {
Ok(role) => {
println!(" ✓ SimpleString 'moderator' deserialized to: {:?}", role);
assert_eq!(role, UserRole::Moderator);
println!(" ✓ SimpleString deserialization works correctly");
}
Err(e) => {
println!(" ❌ SimpleString deserialization failed: {}", e);
return Err(e);
}
}
Ok(())
}
fn test_verbatim_string_case() -> redis::RedisResult<()> {
let verbatim_value = redis::Value::VerbatimString {
format: redis::VerbatimFormat::Text,
text: "regular_user".to_string(),
};
let result: redis::RedisResult<UserRole> = redis::FromRedisValue::from_redis_value(&verbatim_value);
match result {
Ok(role) => {
println!(" ✓ VerbatimString 'regular_user' deserialized to: {:?}", role);
assert_eq!(role, UserRole::RegularUser);
println!(" ✓ VerbatimString deserialization works correctly");
}
Err(e) => {
println!(" ❌ VerbatimString deserialization failed: {}", e);
return Err(e);
}
}
Ok(())
}
fn test_nil_case() -> redis::RedisResult<()> {
let nil_value = redis::Value::Nil;
let result: redis::RedisResult<UserRole> = redis::FromRedisValue::from_redis_value(&nil_value);
match result {
Ok(_) => {
println!(" ❌ Expected error but got success!");
panic!("Nil deserialization should fail");
}
Err(e) => {
println!(" ✓ Nil value correctly rejected with error: {}", e);
println!(" ✓ Nil error handling works correctly");
}
}
Ok(())
}
fn test_invalid_type_case() -> redis::RedisResult<()> {
let int_value = redis::Value::Int(42);
let result: redis::RedisResult<UserRole> = redis::FromRedisValue::from_redis_value(&int_value);
match result {
Ok(_) => {
println!(" ❌ Expected error but got success!");
panic!("Integer deserialization should fail");
}
Err(e) => {
println!(" ✓ Integer value correctly rejected with error: {}", e);
println!(" ✓ Invalid type error handling works correctly");
}
}
let array_value = redis::Value::Array(vec![
redis::Value::SimpleString("not".to_string()),
redis::Value::SimpleString("an".to_string()),
redis::Value::SimpleString("enum".to_string()),
]);
let result: redis::RedisResult<Status> = redis::FromRedisValue::from_redis_value(&array_value);
match result {
Ok(_) => {
println!(" ❌ Expected error but got success!");
panic!("Array deserialization should fail");
}
Err(e) => {
println!(" ✓ Array value correctly rejected with error: {}", e);
println!(" ✓ Array type error handling works correctly");
}
}
Ok(())
}
fn test_invalid_utf8_case() -> redis::RedisResult<()> {
let invalid_utf8_bytes = vec![0xFF, 0xFE, 0xFD]; let bulk_string_value = redis::Value::BulkString(invalid_utf8_bytes);
let result: redis::RedisResult<UserRole> = redis::FromRedisValue::from_redis_value(&bulk_string_value);
match result {
Ok(_) => {
println!(" ❌ Expected UTF-8 error but got success!");
panic!("Invalid UTF-8 deserialization should fail");
}
Err(e) => {
println!(" ✓ Invalid UTF-8 correctly rejected with error: {}", e);
println!(" ✓ UTF-8 validation works correctly");
}
}
Ok(())
}
fn test_unknown_variant_case() -> redis::RedisResult<()> {
let unknown_variant = redis::Value::SimpleString("super_admin".to_string());
let result: redis::RedisResult<UserRole> = redis::FromRedisValue::from_redis_value(&unknown_variant);
match result {
Ok(_) => {
println!(" ❌ Expected unknown variant error but got success!");
panic!("Unknown variant deserialization should fail");
}
Err(e) => {
println!(" ✓ Unknown variant 'super_admin' correctly rejected");
println!(" ✓ Error message: {}", e);
let error_msg = e.to_string();
assert!(error_msg.contains("administrator"));
assert!(error_msg.contains("moderator"));
assert!(error_msg.contains("regular_user"));
assert!(error_msg.contains("guest_user"));
println!(" ✓ Error message includes valid variants list");
println!(" ✓ Unknown variant error handling works correctly");
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_enum_variant_names() {
let admin = UserRole::Administrator;
let args = redis::ToRedisArgs::to_redis_args(&admin);
assert_eq!(args[0], b"administrator");
let regular = UserRole::RegularUser;
let args = redis::ToRedisArgs::to_redis_args(®ular);
assert_eq!(args[0], b"regular_user");
}
#[test]
fn test_status_enum_no_rename() {
let active = Status::Active;
let args = redis::ToRedisArgs::to_redis_args(&active);
assert_eq!(args[0], b"Active");
}
}