//! Rhai wrappers for Redis client module functions //! //! This module provides Rhai wrappers for the functions in the Redis client module. use crate::redisclient; use rhai::{Engine, EvalAltResult, Map}; use std::collections::HashMap; /// Register Redis client module functions with the Rhai engine /// /// # Arguments /// /// * `engine` - The Rhai engine to register the functions with /// /// # Returns /// /// * `Result<(), Box>` - Ok if registration was successful, Err otherwise pub fn register_redisclient_module(engine: &mut Engine) -> Result<(), Box> { // Register basic Redis operations engine.register_fn("redis_ping", redis_ping); engine.register_fn("redis_set", redis_set); engine.register_fn("redis_get", redis_get); engine.register_fn("redis_del", redis_del); // Register hash operations engine.register_fn("redis_hset", redis_hset); engine.register_fn("redis_hget", redis_hget); engine.register_fn("redis_hgetall", redis_hgetall); engine.register_fn("redis_hdel", redis_hdel); // Register list operations engine.register_fn("redis_rpush", redis_rpush); engine.register_fn("redis_lpush", redis_lpush); engine.register_fn("redis_llen", redis_llen); engine.register_fn("redis_lrange", redis_lrange); // Register other operations engine.register_fn("redis_reset", redis_reset); Ok(()) } /// Ping the Redis server /// /// # Returns /// /// * `Result>` - "PONG" if successful, error otherwise pub fn redis_ping() -> Result> { let mut cmd = redis::cmd("PING"); redisclient::execute(&mut cmd).map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, )) }) } /// Set a key-value pair in Redis /// /// # Arguments /// /// * `key` - The key to set /// * `value` - The value to set /// /// # Returns /// /// * `Result>` - true if successful, error otherwise pub fn redis_set(key: &str, value: &str) -> Result> { let mut cmd = redis::cmd("SET"); cmd.arg(key).arg(value); let result: redis::RedisResult = redisclient::execute(&mut cmd); match result { Ok(s) if s == "OK" => Ok(true), Ok(_) => Ok(false), Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } } /// Get a value from Redis by key /// /// # Arguments /// /// * `key` - The key to get /// /// # Returns /// /// * `Result>` - The value if found, empty string if not found, error otherwise pub fn redis_get(key: &str) -> Result> { let mut cmd = redis::cmd("GET"); cmd.arg(key); let result: redis::RedisResult> = redisclient::execute(&mut cmd); match result { Ok(Some(value)) => Ok(value), Ok(None) => Ok(String::new()), Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } } /// Delete a key from Redis /// /// # Arguments /// /// * `key` - The key to delete /// /// # Returns /// /// * `Result>` - true if successful, error otherwise pub fn redis_del(key: &str) -> Result> { let mut cmd = redis::cmd("DEL"); cmd.arg(key); let result: redis::RedisResult = redisclient::execute(&mut cmd); match result { Ok(n) => Ok(n > 0), Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } } /// Set a field in a hash /// /// # Arguments /// /// * `key` - The hash key /// * `field` - The field to set /// * `value` - The value to set /// /// # Returns /// /// * `Result>` - true if successful, error otherwise pub fn redis_hset(key: &str, field: &str, value: &str) -> Result> { let mut cmd = redis::cmd("HSET"); cmd.arg(key).arg(field).arg(value); let result: redis::RedisResult = redisclient::execute(&mut cmd); match result { Ok(_) => Ok(true), Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } } /// Get a field from a hash /// /// # Arguments /// /// * `key` - The hash key /// * `field` - The field to get /// /// # Returns /// /// * `Result>` - The value if found, empty string if not found, error otherwise pub fn redis_hget(key: &str, field: &str) -> Result> { let mut cmd = redis::cmd("HGET"); cmd.arg(key).arg(field); let result: redis::RedisResult> = redisclient::execute(&mut cmd); match result { Ok(Some(value)) => Ok(value), Ok(None) => Ok(String::new()), Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } } /// Get all fields and values from a hash /// /// # Arguments /// /// * `key` - The hash key /// /// # Returns /// /// * `Result>` - A map of field-value pairs, error otherwise pub fn redis_hgetall(key: &str) -> Result> { let mut cmd = redis::cmd("HGETALL"); cmd.arg(key); let result: redis::RedisResult> = redisclient::execute(&mut cmd); match result { Ok(hash_map) => { let mut map = Map::new(); for (k, v) in hash_map { map.insert(k.into(), v.into()); } Ok(map) } Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } } /// Delete a field from a hash /// /// # Arguments /// /// * `key` - The hash key /// * `field` - The field to delete /// /// # Returns /// /// * `Result>` - true if successful, error otherwise pub fn redis_hdel(key: &str, field: &str) -> Result> { let mut cmd = redis::cmd("HDEL"); cmd.arg(key).arg(field); let result: redis::RedisResult = redisclient::execute(&mut cmd); match result { Ok(n) => Ok(n > 0), Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } } /// Push an element to the end of a list /// /// # Arguments /// /// * `key` - The list key /// * `value` - The value to push /// /// # Returns /// /// * `Result>` - The new length of the list, error otherwise pub fn redis_rpush(key: &str, value: &str) -> Result> { let mut cmd = redis::cmd("RPUSH"); cmd.arg(key).arg(value); redisclient::execute(&mut cmd).map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, )) }) } /// Push an element to the beginning of a list /// /// # Arguments /// /// * `key` - The list key /// * `value` - The value to push /// /// # Returns /// /// * `Result>` - The new length of the list, error otherwise pub fn redis_lpush(key: &str, value: &str) -> Result> { let mut cmd = redis::cmd("LPUSH"); cmd.arg(key).arg(value); redisclient::execute(&mut cmd).map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, )) }) } /// Get the length of a list /// /// # Arguments /// /// * `key` - The list key /// /// # Returns /// /// * `Result>` - The length of the list, error otherwise pub fn redis_llen(key: &str) -> Result> { let mut cmd = redis::cmd("LLEN"); cmd.arg(key); redisclient::execute(&mut cmd).map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, )) }) } /// Get a range of elements from a list /// /// # Arguments /// /// * `key` - The list key /// * `start` - The start index /// * `stop` - The stop index /// /// # Returns /// /// * `Result, Box>` - The elements in the range, error otherwise pub fn redis_lrange(key: &str, start: i64, stop: i64) -> Result, Box> { let mut cmd = redis::cmd("LRANGE"); cmd.arg(key).arg(start).arg(stop); redisclient::execute(&mut cmd).map_err(|e| { Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, )) }) } /// Reset the Redis client connection /// /// # Returns /// /// * `Result>` - true if successful, error otherwise pub fn redis_reset() -> Result> { match redisclient::reset() { Ok(_) => Ok(true), Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime( format!("Redis error: {}", e).into(), rhai::Position::NONE, ))), } }