Commit bea5dbfe authored by Marc Gravell's avatar Marc Gravell

Expose ResultType on RedisResult (infer if the existing mock ctors are being used); fixes #21

parent 234ff979
namespace StackExchange.Redis namespace StackExchange.Redis
{ {
internal enum ResultType : byte /// <summary>
/// The underlying result type as defined by redis
/// </summary>
public enum ResultType : byte
{ {
/// <summary>
/// No value was received
/// </summary>
None = 0, None = 0,
/// <summary>
/// Basic strings typically represent status results such as "OK"
/// </summary>
SimpleString = 1, SimpleString = 1,
/// <summary>
/// Error strings represent invalid operation results from the server
/// </summary>
Error = 2, Error = 2,
/// <summary>
/// Integers are returned for count operations and some integer-based increment operations
/// </summary>
Integer = 3, Integer = 3,
/// <summary>
/// Bulk strings represent typical user content values
/// </summary>
BulkString = 4, BulkString = 4,
/// <summary>
/// Multi-bulk replies represent complex results such as arrays
/// </summary>
MultiBulk = 5 MultiBulk = 5
} }
} }
...@@ -12,7 +12,7 @@ public abstract class RedisResult ...@@ -12,7 +12,7 @@ public abstract class RedisResult
/// </summary> /// </summary>
/// <param name="value">The <see cref="RedisValue"/> to create a result from.</param> /// <param name="value">The <see cref="RedisValue"/> to create a result from.</param>
/// <returns> new <see cref="RedisResult"/>.</returns> /// <returns> new <see cref="RedisResult"/>.</returns>
public static RedisResult Create(RedisValue value) => new SingleRedisResult(value); public static RedisResult Create(RedisValue value) => new SingleRedisResult(value, null);
/// <summary> /// <summary>
/// Create a new RedisResult representing an array of values. /// Create a new RedisResult representing an array of values.
...@@ -20,7 +20,7 @@ public abstract class RedisResult ...@@ -20,7 +20,7 @@ public abstract class RedisResult
/// <param name="values">The <see cref="RedisValue"/>s to create a result from.</param> /// <param name="values">The <see cref="RedisValue"/>s to create a result from.</param>
/// <returns> new <see cref="RedisResult"/>.</returns> /// <returns> new <see cref="RedisResult"/>.</returns>
public static RedisResult Create(RedisValue[] values) => new ArrayRedisResult( public static RedisResult Create(RedisValue[] values) => new ArrayRedisResult(
values == null ? null : Array.ConvertAll(values, value => new SingleRedisResult(value))); values == null ? null : Array.ConvertAll(values, value => new SingleRedisResult(value, null)));
// internally, this is very similar to RawResult, except it is designed to be usable // internally, this is very similar to RawResult, except it is designed to be usable
// outside of the IO-processing pipeline: the buffers are standalone, etc // outside of the IO-processing pipeline: the buffers are standalone, etc
...@@ -34,7 +34,7 @@ internal static RedisResult TryCreate(PhysicalConnection connection, RawResult r ...@@ -34,7 +34,7 @@ internal static RedisResult TryCreate(PhysicalConnection connection, RawResult r
case ResultType.Integer: case ResultType.Integer:
case ResultType.SimpleString: case ResultType.SimpleString:
case ResultType.BulkString: case ResultType.BulkString:
return new SingleRedisResult(result.AsRedisValue()); return new SingleRedisResult(result.AsRedisValue(), result.Type);
case ResultType.MultiBulk: case ResultType.MultiBulk:
var items = result.GetItems(); var items = result.GetItems();
var arr = result.IsNull ? null : new RedisResult[items.Length]; var arr = result.IsNull ? null : new RedisResult[items.Length];
...@@ -50,13 +50,18 @@ internal static RedisResult TryCreate(PhysicalConnection connection, RawResult r ...@@ -50,13 +50,18 @@ internal static RedisResult TryCreate(PhysicalConnection connection, RawResult r
default: default:
return null; return null;
} }
} catch(Exception ex) } catch (Exception ex)
{ {
connection?.OnInternalError(ex); connection?.OnInternalError(ex);
return null; // will be logged as a protocol fail by the processor return null; // will be logged as a protocol fail by the processor
} }
} }
/// <summary>
/// Indicate the type of result that was received from redis
/// </summary>
public abstract ResultType ResultType { get; }
/// <summary> /// <summary>
/// Indicates whether this result was a null result /// Indicates whether this result was a null result
/// </summary> /// </summary>
...@@ -193,6 +198,8 @@ private sealed class ArrayRedisResult : RedisResult ...@@ -193,6 +198,8 @@ private sealed class ArrayRedisResult : RedisResult
{ {
public override bool IsNull => value == null; public override bool IsNull => value == null;
private readonly RedisResult[] value; private readonly RedisResult[] value;
public override ResultType ResultType => ResultType.MultiBulk;
public ArrayRedisResult(RedisResult[] value) public ArrayRedisResult(RedisResult[] value)
{ {
this.value = value ?? throw new ArgumentNullException(nameof(value)); this.value = value ?? throw new ArgumentNullException(nameof(value));
...@@ -294,6 +301,8 @@ internal override string AsString() ...@@ -294,6 +301,8 @@ internal override string AsString()
private sealed class ErrorRedisResult : RedisResult private sealed class ErrorRedisResult : RedisResult
{ {
private readonly string value; private readonly string value;
public override ResultType ResultType => ResultType.Error;
public ErrorRedisResult(string value) public ErrorRedisResult(string value)
{ {
this.value = value ?? throw new ArgumentNullException(nameof(value)); this.value = value ?? throw new ArgumentNullException(nameof(value));
...@@ -326,35 +335,38 @@ public ErrorRedisResult(string value) ...@@ -326,35 +335,38 @@ public ErrorRedisResult(string value)
private sealed class SingleRedisResult : RedisResult private sealed class SingleRedisResult : RedisResult
{ {
private readonly RedisValue value; private readonly RedisValue _value;
public SingleRedisResult(RedisValue value) private readonly ResultType _resultType;
public override ResultType ResultType => _resultType;
public SingleRedisResult(RedisValue value, ResultType? resultType)
{ {
this.value = value; _value = value;
_resultType = resultType ?? (value.IsInteger ? ResultType.Integer : ResultType.BulkString);
} }
public override bool IsNull => value.IsNull; public override bool IsNull => _value.IsNull;
public override string ToString() => value.ToString(); public override string ToString() => _value.ToString();
internal override bool AsBoolean() => (bool)value; internal override bool AsBoolean() => (bool)_value;
internal override bool[] AsBooleanArray() => new[] { AsBoolean() }; internal override bool[] AsBooleanArray() => new[] { AsBoolean() };
internal override byte[] AsByteArray() => (byte[])value; internal override byte[] AsByteArray() => (byte[])_value;
internal override byte[][] AsByteArrayArray() => new[] { AsByteArray() }; internal override byte[][] AsByteArrayArray() => new[] { AsByteArray() };
internal override double AsDouble() => (double)value; internal override double AsDouble() => (double)_value;
internal override double[] AsDoubleArray() => new[] { AsDouble() }; internal override double[] AsDoubleArray() => new[] { AsDouble() };
internal override int AsInt32() => (int)value; internal override int AsInt32() => (int)_value;
internal override int[] AsInt32Array() => new[] { AsInt32() }; internal override int[] AsInt32Array() => new[] { AsInt32() };
internal override long AsInt64() => (long)value; internal override long AsInt64() => (long)_value;
internal override long[] AsInt64Array() => new[] { AsInt64() }; internal override long[] AsInt64Array() => new[] { AsInt64() };
internal override bool? AsNullableBoolean() => (bool?)value; internal override bool? AsNullableBoolean() => (bool?)_value;
internal override double? AsNullableDouble() => (double?)value; internal override double? AsNullableDouble() => (double?)_value;
internal override int? AsNullableInt32() => (int?)value; internal override int? AsNullableInt32() => (int?)_value;
internal override long? AsNullableInt64() => (long?)value; internal override long? AsNullableInt64() => (long?)_value;
internal override RedisKey AsRedisKey() => (byte[])value; internal override RedisKey AsRedisKey() => (byte[])_value;
internal override RedisKey[] AsRedisKeyArray() => new[] { AsRedisKey() }; internal override RedisKey[] AsRedisKeyArray() => new[] { AsRedisKey() };
internal override RedisResult[] AsRedisResultArray() => throw new InvalidCastException(); internal override RedisResult[] AsRedisResultArray() => throw new InvalidCastException();
internal override RedisValue AsRedisValue() => value; internal override RedisValue AsRedisValue() => _value;
internal override RedisValue[] AsRedisValueArray() => new[] { AsRedisValue() }; internal override RedisValue[] AsRedisValueArray() => new[] { AsRedisValue() };
internal override string AsString() => (string)value; internal override string AsString() => (string)_value;
internal override string[] AsStringArray() => new[] { AsString() }; internal override string[] AsStringArray() => new[] { AsString() };
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment