using CommandLine; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using RedisManager.Utils; using RedisManager.Commands; namespace RedisManager.Commands { [Verb("bitcount", HelpText = "Count set bits in a string.")] public class BitCountOptions : InstanceOptions { [Value(0, MetaName = "key", Required = true, HelpText = "Key name.")] public string Key { get; set; } [Option("start", Default = 0L, HelpText = "Start byte.")] public long Start { get; set; } [Option("end", Default = -1L, HelpText = "End byte.")] public long End { get; set; } } [Verb("bitfield", HelpText = "Perform arbitrary bitfield integer operations on strings.")] public class BitFieldOptions : InstanceOptions { [Value(0, MetaName = "key", Required = true, HelpText = "Key name.")] public string Key { get; set; } [Value(1, MetaName = "operations", Min = 1, Required = true, HelpText = "Bitfield operations.")] public IEnumerable Operations { get; set; } } [Verb("bitop", HelpText = "Perform bitwise operations between strings.")] public class BitOpOptions : InstanceOptions { [Value(0, MetaName = "operation", Required = true, HelpText = "Operation (AND, OR, XOR, NOT).")] public string Operation { get; set; } [Value(1, MetaName = "dest-key", Required = true, HelpText = "Destination key.")] public string DestKey { get; set; } [Value(2, MetaName = "source-keys", Min = 1, Required = true, HelpText = "Source keys.")] public IEnumerable SourceKeys { get; set; } } [Verb("bitpos", HelpText = "Find first bit set or clear in a string.")] public class BitPosOptions : InstanceOptions { [Value(0, MetaName = "key", Required = true, HelpText = "Key name.")] public string Key { get; set; } [Value(1, MetaName = "bit", Required = true, HelpText = "Bit value (0 or 1).")] public int Bit { get; set; } [Option("start", Default = 0L, HelpText = "Start byte.")] public long Start { get; set; } [Option("end", Default = -1L, HelpText = "End byte.")] public long End { get; set; } } [Verb("getbit", HelpText = "Returns the bit value at offset in the string value stored at key.")] public class GetBitOptions : InstanceOptions { [Value(0, MetaName = "key", Required = true, HelpText = "Key name.")] public string Key { get; set; } [Value(1, MetaName = "offset", Required = true, HelpText = "Bit offset.")] public long Offset { get; set; } } [Verb("setbit", HelpText = "Sets or clears the bit at offset in the string value stored at key.")] public class SetBitOptions : InstanceOptions { [Value(0, MetaName = "key", Required = true, HelpText = "Key name.")] public string Key { get; set; } [Value(1, MetaName = "offset", Required = true, HelpText = "Bit offset.")] public long Offset { get; set; } [Value(2, MetaName = "bit", Required = true, HelpText = "Bit value (0 or 1).")] public int Bit { get; set; } } public static class BitCommands { /// /// Executes the BITCOUNT command to count set bits in a string. /// /// The BitCountOptions containing instance, key, start, and end. /// The RedisManager configuration. /// Exit code (0 for success, non-zero for failure). public static int RunBitCount(BitCountOptions opts, Config config) { var instance = RedisUtils.GetInstance(config, opts.Instance); using var redis = RedisUtils.ConnectRedis(instance); var db = redis.GetDatabase(); var args = new List { opts.Key }; if (opts.Start != 0 || opts.End != -1) { args.Add(opts.Start); args.Add(opts.End); } var result = db.Execute("BITCOUNT", args.ToArray()); Console.WriteLine(Output.Green($"Bit count: {result}")); return 0; } /// /// Executes the BITFIELD command to perform arbitrary bitfield integer operations on strings. /// /// The BitFieldOptions containing instance, key, and operations. /// The RedisManager configuration. /// Exit code (0 for success, non-zero for failure). public static int RunBitField(BitFieldOptions opts, Config config) { var instance = RedisUtils.GetInstance(config, opts.Instance); using var redis = RedisUtils.ConnectRedis(instance); var db = redis.GetDatabase(); var args = new List { opts.Key }; args.AddRange(opts.Operations); var result = db.Execute("BITFIELD", args.ToArray()); RedisResult[] results; if (result is Array) results = (RedisResult[])result; else results = new RedisResult[] { result }; Console.WriteLine(Output.Green("Bitfield results:")); var operationsList = opts.Operations.ToList(); for (int i = 0; results != null && i < results.Length; i++) { var res = results[i]; if (res != null) { Console.WriteLine(Output.Cyan($"{operationsList[i]}: {res}")); } else { Console.WriteLine(Output.Red($"{operationsList[i]}: null")); } } return 0; } /// /// Executes the BITOP command to perform bitwise operations between strings. /// /// The BitOpOptions containing instance, operation, destination key, and source keys. /// The RedisManager configuration. /// Exit code (0 for success, non-zero for failure). public static int RunBitOp(BitOpOptions opts, Config config) { var instance = RedisUtils.GetInstance(config, opts.Instance); using var redis = RedisUtils.ConnectRedis(instance); var db = redis.GetDatabase(); var args = new List { opts.Operation, opts.DestKey }; args.AddRange(opts.SourceKeys); var result = db.Execute("BITOP", args.ToArray()); Console.WriteLine(Output.Green($"BITOP result: {result}")); return 0; } /// /// Executes the BITPOS command to find the first bit set or clear in a string. /// /// The BitPosOptions containing instance, key, bit, start, and end. /// The RedisManager configuration. /// Exit code (0 for success, non-zero for failure). public static int RunBitPos(BitPosOptions opts, Config config) { var instance = RedisUtils.GetInstance(config, opts.Instance); using var redis = RedisUtils.ConnectRedis(instance); var db = redis.GetDatabase(); var args = new List { opts.Key, opts.Bit }; if (opts.Start != 0 || opts.End != -1) { args.Add(opts.Start); args.Add(opts.End); } var result = db.Execute("BITPOS", args.ToArray()); Console.WriteLine(Output.Green($"First {opts.Bit} bit at position: {result}")); return 0; } /// /// Executes the GETBIT command to return the bit value at offset in the string value stored at key. /// /// The GetBitOptions containing instance, key, and offset. /// The RedisManager configuration. /// Exit code (0 for success, non-zero for failure). public static int RunGetBit(GetBitOptions opts, Config config) { var instance = RedisUtils.GetInstance(config, opts.Instance); using var redis = RedisUtils.ConnectRedis(instance); var db = redis.GetDatabase(); var result = db.Execute("GETBIT", new object[] { opts.Key, opts.Offset }); Console.WriteLine(Output.Green($"Bit at offset {opts.Offset}: {result}")); return 0; } /// /// Executes the SETBIT command to set or clear the bit at offset in the string value stored at key. /// /// The SetBitOptions containing instance, key, offset, and bit value. /// The RedisManager configuration. /// Exit code (0 for success, non-zero for failure). public static int RunSetBit(SetBitOptions opts, Config config) { var instance = RedisUtils.GetInstance(config, opts.Instance); using var redis = RedisUtils.ConnectRedis(instance); var db = redis.GetDatabase(); var result = db.Execute("SETBIT", new object[] { opts.Key, opts.Offset, opts.Bit }); Console.WriteLine(Output.Green($"Set bit at offset {opts.Offset} to {opts.Bit}: {result}")); return 0; } } }