{"id":19847763,"url":"https://github.com/kkharji/redis-derive","last_synced_at":"2025-10-09T01:13:25.574Z","repository":{"id":45796063,"uuid":"464425899","full_name":"kkharji/redis-derive","owner":"kkharji","description":"This crate implements the FromRedisValue and ToRedisArgs Traits from mitsuhiko / redis-rs for any struct","archived":false,"fork":false,"pushed_at":"2025-08-07T20:37:46.000Z","size":4061,"stargazers_count":21,"open_issues_count":5,"forks_count":9,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-09T01:12:40.065Z","etag":null,"topics":["crates","redis","rust","rust-proc-macro","serde","serde-redis"],"latest_commit_sha":null,"homepage":"https://docs.rs/redis-derive/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kkharji.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-02-28T09:55:09.000Z","updated_at":"2025-10-02T09:52:28.000Z","dependencies_parsed_at":"2024-11-12T13:15:07.022Z","dependency_job_id":"21ff2115-bf87-4baa-9237-1ec46c7510ae","html_url":"https://github.com/kkharji/redis-derive","commit_stats":null,"previous_names":["michaelvanstraten/redis-derive"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kkharji/redis-derive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kkharji%2Fredis-derive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kkharji%2Fredis-derive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kkharji%2Fredis-derive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kkharji%2Fredis-derive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kkharji","download_url":"https://codeload.github.com/kkharji/redis-derive/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kkharji%2Fredis-derive/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000726,"owners_count":26082894,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crates","redis","rust","rust-proc-macro","serde","serde-redis"],"created_at":"2024-11-12T13:15:04.919Z","updated_at":"2025-10-09T01:13:25.569Z","avatar_url":"https://github.com/kkharji.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# redis-derive\n\n## redis-derive\n\nThis crate implements the `FromRedisValue`(redis::FromRedisValue) and `ToRedisArgs`(redis::ToRedisArgs) traits\nfrom `redis-rs`(https://github.com/redis-rs/redis-rs) for any struct or enum.\n\nThis allows seamless type conversion between Rust structs and Redis hash sets, which is more beneficial than JSON encoding the struct and storing the result in a Redis key because when saving as a Redis hash set, sorting algorithms can be performed without having to move data out of the database.\n\nThere is also the benefit of being able to retrieve just one value of the struct in the database.\n\nInitial development was done by @Michaelvanstraten 🙏🏽.\n\n### Features\n\n- **RESP3 Support**: Native support for Redis 7+ protocol features including VerbatimString\n- **Hash Field Expiration**: Per-field TTL support using Redis 7.4+ HEXPIRE commands\n- **Client-Side Caching**: Automatic cache management with Redis 6+ client caching\n- **Cluster Awareness**: Hash tag generation for Redis Cluster deployments\n- **Flexible Naming**: Support for various case conversion rules (snake_case, kebab-case, etc.)\n- **Comprehensive Error Handling**: Clear error messages for debugging\n- **Performance Optimized**: Efficient serialization with minimal allocations\n\n### Usage and Examples\n\nAdd this to your `Cargo.toml`:\n\n```toml\n[dependencies]\nredis-derive = \"0.2.0\"\nredis = \"0.32\"\n```\n\nImport the procedural macros:\n\n```rust\nuse redis_derive::{FromRedisValue, ToRedisArgs};\n```\n\n#### Basic Struct Example\n\n```rust\nuse redis::Commands;\nuse redis_derive::{FromRedisValue, ToRedisArgs};\n\n#[derive(ToRedisArgs, FromRedisValue, Debug)]\nstruct User {\n    id: u64,\n    username: String,\n    email: Option\u003cString\u003e,\n    active: bool,\n}\n\nfn main() -\u003e redis::RedisResult\u003c()\u003e {\n    let client = redis::Client::open(\"redis://127.0.0.1/\")?;\n    let mut con = client.get_connection()?;\n\n    let user = User {\n        id: 12345,\n        username: \"john_doe\".to_string(),\n        email: Some(\"john@example.com\".to_string()),\n        active: true,\n    };\n\n    // Store individual fields\n    con.hset(\"user:12345\", \"id\", user.id)?;\n    con.hset(\"user:12345\", \"username\", \u0026user.username)?;\n    con.hset(\"user:12345\", \"email\", \u0026user.email)?;\n    con.hset(\"user:12345\", \"active\", user.active)?;\n\n    // Retrieve the complete struct\n    let retrieved_user: User = con.hgetall(\"user:12345\")?;\n    println!(\"Retrieved: {:?}\", retrieved_user);\n\n    Ok(())\n}\n```\n\n#### Enum with Case Conversion\n\n```rust\n#[derive(ToRedisArgs, FromRedisValue, Debug, PartialEq)]\n#[redis(rename_all = \"snake_case\")]\nenum UserRole {\n    Administrator,      // stored as \"administrator\"\n    PowerUser,          // stored as \"power_user\"\n    RegularUser,        // stored as \"regular_user\"\n    GuestUser,          // stored as \"guest_user\"\n}\n\n// Works seamlessly with Redis\nlet role = UserRole::PowerUser;\ncon.set(\"user:role\", \u0026role)?;\nlet retrieved: UserRole = con.get(\"user:role\")?;\nassert_eq!(role, retrieved);\n```\n\n### Naming Conventions and Attributes\n\n#### Case Conversion Rules\n\nThe `rename_all` attribute supports multiple case conversion rules:\n\n```rust\n#[derive(ToRedisArgs, FromRedisValue)]\n#[redis(rename_all = \"snake_case\")]\nenum Status {\n    InProgress,        // → \"in_progress\"\n    WaitingForReview,  // → \"waiting_for_review\"\n    Completed,         // → \"completed\"\n}\n\n#[derive(ToRedisArgs, FromRedisValue)]\n#[redis(rename_all = \"kebab-case\")]\nenum Priority {\n    HighPriority,      // → \"high-priority\"\n    MediumPriority,    // → \"medium-priority\"\n    LowPriority,       // → \"low-priority\"\n}\n```\n\nSupported case conversion rules:\n- `\"lowercase\"`: `MyField` → `myfield`\n- `\"UPPERCASE\"`: `MyField` → `MYFIELD`\n- `\"PascalCase\"`: `my_field` → `MyField`\n- `\"camelCase\"`: `my_field` → `myField`\n- `\"snake_case\"`: `MyField` → `my_field`\n- `\"kebab-case\"`: `MyField` → `my-field`\n\n#### Important Naming Behavior\n\n**Key insight**: The case conversion applies to **both** serialization and deserialization:\n\n```rust\n// With rename_all = \"snake_case\"\nlet role = UserRole::PowerUser;\n\n// Serialization: PowerUser → \"power_user\"\ncon.set(\"key\", \u0026role)?;\n\n// Deserialization: \"power_user\" → PowerUser\nlet retrieved: UserRole = con.get(\"key\")?;\n\n// Error messages also use converted names:\n// \"Unknown variant 'admin' for UserRole. Valid variants: [administrator, power_user, regular_user, guest_user]\"\n```\n\n#### Redis Protocol Support\n\nThis crate handles multiple Redis value types automatically:\n\n- **BulkString**: Most common for stored hash fields and string values\n- **SimpleString**: Direct Redis command responses\n- **VerbatimString**: Redis 6+ RESP3 protocol feature (automatically supported)\n- **Proper error handling**: Clear messages for nil values and type mismatches\n\n#### Advanced Features\n\n##### Hash Field Expiration (Redis 7.4+)\n```rust\n#[derive(ToRedisArgs, FromRedisValue)]\nstruct SessionData {\n    user_id: u64,\n    #[redis(expire = \"1800\")] // 30 minutes\n    access_token: String,\n    #[redis(expire = \"7200\")] // 2 hours\n    refresh_token: String,\n}\n```\n\n##### Cluster-Aware Keys\n```rust\n#[derive(ToRedisArgs, FromRedisValue)]\n#[redis(cluster_key = \"user_id\")]\nstruct UserProfile {\n    user_id: u64,\n    profile_data: String,\n}\n```\n\n##### Client-Side Caching\n```rust\n#[derive(ToRedisArgs, FromRedisValue)]\n#[redis(cache = true, ttl = \"600\")]\nstruct CachedData {\n    id: u64,\n    data: String,\n}\n```\n\n### Development and Testing\n\nThe crate includes comprehensive examples in the `examples/` directory:\n\n```bash\n# Start Redis with Docker\ncd examples \u0026\u0026 docker-compose up -d\n\n# Run basic example\ncargo run --example main\n\n# Test all enum deserialization branches\ncargo run --example enum_branches\n\n# Debug attribute parsing behavior\ncargo run --example debug_attributes\n```\n\n### Limitations\n\n- Only unit enums (variants without fields) are currently supported\n- Requires redis-rs 0.32.4 or later for full compatibility\n\n### Compatibility\n\n- **Redis**: Compatible with Redis 6+ (RESP2) and Redis 7+ (RESP3)\n- **Rust**: MSRV 1.70+ (follows redis-rs requirements)\n- **redis-rs**: 0.32.4+ (uses `num_of_args()` instead of deprecated `num_args()`)\n\nLicense: MIT OR Apache-2.0\n\nLicense: MIT OR Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkkharji%2Fredis-derive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkkharji%2Fredis-derive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkkharji%2Fredis-derive/lists"}