Advertisement
davidmk

Untitled

Dec 3rd, 2019
687
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.50 KB | None | 0 0
  1. using System;
  2. using System.Text;
  3. using System.Linq;
  4.  
  5. namespace StackExchange.Redis
  6. {
  7.     /// <summary>
  8.     /// Represents a pub/sub channel name
  9.     /// </summary>
  10.     public struct RedisChannel : IEquatable<RedisChannel>
  11.     {
  12.         internal static readonly RedisChannel[] EmptyArray = new RedisChannel[0];
  13.         private static readonly byte[] __keyBytes = Encoding.UTF8.GetBytes("__key");
  14.         private static readonly byte[] __KEYBytes = Encoding.UTF8.GetBytes("__KEY");
  15.  
  16.         internal readonly byte[] Value;
  17.         internal readonly bool IsPatternBased;
  18.         internal readonly bool IsKeyspaceChannel;
  19.  
  20.         /// <summary>
  21.         /// Indicates whether the channel-name is either null or a zero-length value
  22.         /// </summary>
  23.         public bool IsNullOrEmpty => Value == null || Value.Length == 0;
  24.  
  25.         internal bool IsNull => Value == null;
  26.  
  27.         /// <summary>
  28.         /// Create a new redis channel from a buffer, explicitly controlling the pattern mode
  29.         /// </summary>
  30.         /// <param name="value">The name of the channel to create.</param>
  31.         /// <param name="mode">The mode for name matching.</param>
  32.         public RedisChannel(byte[] value, PatternMode mode) : this(value, DeterminePatternBased(value, mode)) {}
  33.  
  34.         /// <summary>
  35.         /// Create a new redis channel from a string, explicitly controlling the pattern mode
  36.         /// </summary>
  37.         /// <param name="value">The string name of the channel to create.</param>
  38.         /// <param name="mode">The mode for name matching.</param>
  39.         public RedisChannel(string value, PatternMode mode) : this(value == null ? null : Encoding.UTF8.GetBytes(value), mode) {}
  40.  
  41.         private RedisChannel(byte[] value, bool isPatternBased)
  42.         {
  43.             Value = value;
  44.             IsPatternBased = isPatternBased;
  45.            
  46.             if(value != null && value.Length >= __keyBytes.Length)
  47.             {
  48.                 var prefix = new ArraySegment<byte>(value, 0, 5);
  49.                 IsKeyspaceChannel = prefix.SequenceEqual(__keyBytes) || prefix.SequenceEqual(__KEYBytes);
  50.             }
  51.             else
  52.             {
  53.                 IsKeyspaceChannel = false;
  54.             }
  55.         }
  56.  
  57.         private static bool DeterminePatternBased(byte[] value, PatternMode mode)
  58.         {
  59.             switch (mode)
  60.             {
  61.                 case PatternMode.Auto:
  62.                     return value != null && Array.IndexOf(value, (byte)'*') >= 0;
  63.                 case PatternMode.Literal: return false;
  64.                 case PatternMode.Pattern: return true;
  65.                 default:
  66.                     throw new ArgumentOutOfRangeException(nameof(mode));
  67.             }
  68.         }
  69.  
  70.         /// <summary>
  71.         /// Indicate whether two channel names are not equal
  72.         /// </summary>
  73.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  74.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  75.         public static bool operator !=(RedisChannel x, RedisChannel y) => !(x == y);
  76.  
  77.         /// <summary>
  78.         /// Indicate whether two channel names are not equal
  79.         /// </summary>
  80.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  81.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  82.         public static bool operator !=(string x, RedisChannel y) => !(x == y);
  83.  
  84.         /// <summary>
  85.         /// Indicate whether two channel names are not equal
  86.         /// </summary>
  87.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  88.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  89.         public static bool operator !=(byte[] x, RedisChannel y) => !(x == y);
  90.  
  91.         /// <summary>
  92.         /// Indicate whether two channel names are not equal
  93.         /// </summary>
  94.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  95.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  96.         public static bool operator !=(RedisChannel x, string y) => !(x == y);
  97.  
  98.         /// <summary>
  99.         /// Indicate whether two channel names are not equal
  100.         /// </summary>
  101.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  102.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  103.         public static bool operator !=(RedisChannel x, byte[] y) => !(x == y);
  104.  
  105.         /// <summary>
  106.         /// Indicate whether two channel names are equal
  107.         /// </summary>
  108.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  109.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  110.         public static bool operator ==(RedisChannel x, RedisChannel y) =>
  111.             x.IsPatternBased == y.IsPatternBased && RedisValue.Equals(x.Value, y.Value);
  112.  
  113.         /// <summary>
  114.         /// Indicate whether two channel names are equal
  115.         /// </summary>
  116.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  117.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  118.         public static bool operator ==(string x, RedisChannel y) =>
  119.             RedisValue.Equals(x == null ? null : Encoding.UTF8.GetBytes(x), y.Value);
  120.  
  121.         /// <summary>
  122.         /// Indicate whether two channel names are equal
  123.         /// </summary>
  124.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  125.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  126.         public static bool operator ==(byte[] x, RedisChannel y) => RedisValue.Equals(x, y.Value);
  127.  
  128.         /// <summary>
  129.         /// Indicate whether two channel names are equal
  130.         /// </summary>
  131.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  132.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  133.         public static bool operator ==(RedisChannel x, string y) =>
  134.             RedisValue.Equals(x.Value, y == null ? null : Encoding.UTF8.GetBytes(y));
  135.  
  136.         /// <summary>
  137.         /// Indicate whether two channel names are equal
  138.         /// </summary>
  139.         /// <param name="x">The first <see cref="RedisChannel"/> to compare.</param>
  140.         /// <param name="y">The second <see cref="RedisChannel"/> to compare.</param>
  141.         public static bool operator ==(RedisChannel x, byte[] y) => RedisValue.Equals(x.Value, y);
  142.  
  143.         /// <summary>
  144.         /// See Object.Equals
  145.         /// </summary>
  146.         /// <param name="obj">The <see cref="RedisChannel"/> to compare to.</param>
  147.         public override bool Equals(object obj)
  148.         {
  149.             if (obj is RedisChannel rcObj)
  150.             {
  151.                 return RedisValue.Equals(Value, (rcObj).Value);
  152.             }
  153.             if (obj is string sObj)
  154.             {
  155.                 return RedisValue.Equals(Value, Encoding.UTF8.GetBytes(sObj));
  156.             }
  157.             if (obj is byte[] bObj)
  158.             {
  159.                 return RedisValue.Equals(Value, bObj);
  160.             }
  161.             return false;
  162.         }
  163.  
  164.         /// <summary>
  165.         /// Indicate whether two channel names are equal
  166.         /// </summary>
  167.         /// <param name="other">The <see cref="RedisChannel"/> to compare to.</param>
  168.         public bool Equals(RedisChannel other) => IsPatternBased == other.IsPatternBased && RedisValue.Equals(Value, other.Value);
  169.  
  170.         /// <summary>
  171.         /// See Object.GetHashCode
  172.         /// </summary>
  173.         public override int GetHashCode() => RedisValue.GetHashCode(Value) + (IsPatternBased ? 1 : 0);
  174.  
  175.         /// <summary>
  176.         /// Obtains a string representation of the channel name
  177.         /// </summary>
  178.         public override string ToString()
  179.         {
  180.             return ((string)this) ?? "(null)";
  181.         }
  182.  
  183.         internal static bool AssertStarts(byte[] value, byte[] expected)
  184.         {
  185.             for (int i = 0; i < expected.Length; i++)
  186.             {
  187.                 if (expected[i] != value[i]) return false;
  188.             }
  189.             return true;
  190.         }
  191.  
  192.         internal void AssertNotNull()
  193.         {
  194.             if (IsNull) throw new ArgumentException("A null key is not valid in this context");
  195.         }
  196.  
  197.         internal RedisChannel Clone() => (byte[])Value?.Clone();
  198.  
  199.         /// <summary>
  200.         /// The matching pattern for this channel
  201.         /// </summary>
  202.         public enum PatternMode
  203.         {
  204.             /// <summary>
  205.             /// Will be treated as a pattern if it includes *
  206.             /// </summary>
  207.             Auto = 0,
  208.             /// <summary>
  209.             /// Never a pattern
  210.             /// </summary>
  211.             Literal = 1,
  212.             /// <summary>
  213.             /// Always a pattern
  214.             /// </summary>
  215.             Pattern = 2
  216.         }
  217.  
  218.         /// <summary>
  219.         /// Create a channel name from a <see cref="string"/>.
  220.         /// </summary>
  221.         /// <param name="key">The string to get a channel from.</param>
  222.         public static implicit operator RedisChannel(string key)
  223.         {
  224.             if (key == null) return default(RedisChannel);
  225.             return new RedisChannel(Encoding.UTF8.GetBytes(key), PatternMode.Auto);
  226.         }
  227.  
  228.         /// <summary>
  229.         /// Create a channel name from a <see cref="T:byte[]"/>.
  230.         /// </summary>
  231.         /// <param name="key">The byte array to get a channel from.</param>
  232.         public static implicit operator RedisChannel(byte[] key)
  233.         {
  234.             if (key == null) return default(RedisChannel);
  235.             return new RedisChannel(key, PatternMode.Auto);
  236.         }
  237.  
  238.         /// <summary>
  239.         /// Obtain the channel name as a <see cref="T:byte[]"/>.
  240.         /// </summary>
  241.         /// <param name="key">The channel to get a byte[] from.</param>
  242.         public static implicit operator byte[] (RedisChannel key) => key.Value;
  243.  
  244.         /// <summary>
  245.         /// Obtain the channel name as a <see cref="string"/>.
  246.         /// </summary>
  247.         /// <param name="key">The channel to get a string from.</param>
  248.         public static implicit operator string (RedisChannel key)
  249.         {
  250.             var arr = key.Value;
  251.             if (arr == null) return null;
  252.             try
  253.             {
  254.                 return Encoding.UTF8.GetString(arr);
  255.             }
  256.             catch
  257.             {
  258.                 return BitConverter.ToString(arr);
  259.             }
  260.         }
  261.     }
  262. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement