11using System ;
22using System . Collections . Generic ;
3+ using RESPite . Messages ;
34
45namespace StackExchange . Redis
56{
@@ -372,7 +373,8 @@ public static Condition StringNotEqual(RedisKey key, RedisValue value)
372373 internal abstract IEnumerable < Message > CreateMessages ( int db , IResultBox ? resultBox ) ;
373374
374375 internal abstract int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) ;
375- internal abstract bool TryValidate ( in RawResult result , out bool value ) ;
376+
377+ internal abstract bool TryValidate ( ref RespReader reader , out bool value ) ;
376378
377379 internal sealed class ConditionProcessor : ResultProcessor < bool >
378380 {
@@ -387,13 +389,12 @@ public static Message CreateMessage(Condition condition, int db, CommandFlags fl
387389 public static Message CreateMessage ( Condition condition , int db , CommandFlags flags , RedisCommand command , in RedisKey key , in RedisValue value , in RedisValue value1 , in RedisValue value2 , in RedisValue value3 , in RedisValue value4 ) =>
388390 new ConditionMessage ( condition , db , flags , command , key , value , value1 , value2 , value3 , value4 ) ;
389391
390- [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Style" , "IDE0071:Simplify interpolation" , Justification = "Allocations (string.Concat vs. string.Format)" ) ]
391- protected override bool SetResultCore ( PhysicalConnection connection , Message message , RawResult result )
392+ protected override bool SetResultCore ( PhysicalConnection connection , Message message , ref RespReader reader )
392393 {
393- connection ? . BridgeCouldBeNull ? . Multiplexer ? . OnTransactionLog ( $ "condition '{ message . CommandAndKey } ' got '{ result . ToString ( ) } '") ;
394+ connection ? . BridgeCouldBeNull ? . Multiplexer ? . OnTransactionLog ( $ "condition '{ message . CommandAndKey } ' got '{ reader . GetOverview ( ) } '") ;
394395 var msg = message as ConditionMessage ;
395396 var condition = msg ? . Condition ;
396- if ( condition != null && condition . TryValidate ( result , out bool final ) )
397+ if ( condition != null && condition . TryValidate ( ref reader , out bool final ) )
397398 {
398399 SetResult ( message , final ) ;
399400 return true ;
@@ -510,19 +511,20 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
510511
511512 internal override int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) => serverSelectionStrategy . HashSlot ( key ) ;
512513
513- internal override bool TryValidate ( in RawResult result , out bool value )
514+ internal override bool TryValidate ( ref RespReader reader , out bool value )
514515 {
515516 switch ( type )
516517 {
517518 case RedisType . SortedSet :
518- var parsedValue = result . AsRedisValue ( ) ;
519- value = parsedValue . IsNull != expectedResult ;
520- ConnectionMultiplexer . TraceWithoutContext ( "exists: " + parsedValue + "; expected: " + expectedResult + "; voting: " + value ) ;
519+ // ZSCORE returns bulk string (score) or null
520+ var parsedValue = reader . IsNull ;
521+ value = parsedValue != expectedResult ;
522+ ConnectionMultiplexer . TraceWithoutContext ( "exists: " + ! parsedValue + "; expected: " + expectedResult + "; voting: " + value ) ;
521523 return true ;
522524
523525 default :
524- bool parsed ;
525- if ( ResultProcessor . DemandZeroOrOneProcessor . TryGet ( result , out parsed ) )
526+ // EXISTS, HEXISTS, SISMEMBER return integer 0 or 1
527+ if ( ResultProcessor . DemandZeroOrOneProcessor . TryGet ( ref reader , out bool parsed ) )
526528 {
527529 value = parsed == expectedResult ;
528530 ConnectionMultiplexer . TraceWithoutContext ( "exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value ) ;
@@ -586,12 +588,30 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
586588
587589 internal override int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) => serverSelectionStrategy . HashSlot ( key ) ;
588590
589- internal override bool TryValidate ( in RawResult result , out bool value )
591+ internal override bool TryValidate ( ref RespReader reader , out bool value )
590592 {
591- value = result . ItemsCount == 1 && result [ 0 ] . AsRedisValue ( ) . StartsWith ( prefix ) ;
592-
593- if ( ! expectedResult ) value = ! value ;
594- return true ;
593+ // ZRANGEBYLEX returns an array with 0 or 1 elements
594+ if ( reader . IsAggregate )
595+ {
596+ var count = reader . AggregateLength ( ) ;
597+ if ( count == 1 )
598+ {
599+ // Check if the first element starts with prefix
600+ if ( reader . TryMoveNext ( ) && reader . IsScalar )
601+ {
602+ value = reader . ReadRedisValue ( ) . StartsWith ( prefix ) ;
603+ if ( ! expectedResult ) value = ! value ;
604+ return true ;
605+ }
606+ }
607+ else if ( count == 0 )
608+ {
609+ value = ! expectedResult ; // No match found
610+ return true ;
611+ }
612+ }
613+ value = false ;
614+ return false ;
595615 }
596616 }
597617
@@ -640,13 +660,21 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
640660
641661 internal override int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) => serverSelectionStrategy . HashSlot ( key ) ;
642662
643- internal override bool TryValidate ( in RawResult result , out bool value )
663+ internal override bool TryValidate ( ref RespReader reader , out bool value )
644664 {
665+ // All commands (ZSCORE, GET, HGET) return scalar values
666+ if ( ! reader . IsScalar )
667+ {
668+ value = false ;
669+ return false ;
670+ }
671+
645672 switch ( type )
646673 {
647674 case RedisType . SortedSet :
675+ // ZSCORE returns bulk string (score as double) or null
648676 var parsedValue = RedisValue . Null ;
649- if ( ! result . IsNull && result . TryGetDouble ( out var val ) )
677+ if ( ! reader . IsNull && reader . TryReadDouble ( out var val ) )
650678 {
651679 parsedValue = val ;
652680 }
@@ -657,19 +685,12 @@ internal override bool TryValidate(in RawResult result, out bool value)
657685 return true ;
658686
659687 default :
660- switch ( result . Resp2TypeBulkString )
661- {
662- case ResultType . BulkString :
663- case ResultType . SimpleString :
664- case ResultType . Integer :
665- var parsed = result . AsRedisValue ( ) ;
666- value = ( parsed == expectedValue ) == expectedEqual ;
667- ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsed + "; expected: " + ( string ? ) expectedValue +
668- "; wanted: " + ( expectedEqual ? "==" : "!=" ) + "; voting: " + value ) ;
669- return true ;
670- }
671- value = false ;
672- return false ;
688+ // GET or HGET returns bulk string, simple string, or integer
689+ var parsed = reader . ReadRedisValue ( ) ;
690+ value = ( parsed == expectedValue ) == expectedEqual ;
691+ ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsed + "; expected: " + ( string ? ) expectedValue +
692+ "; wanted: " + ( expectedEqual ? "==" : "!=" ) + "; voting: " + value ) ;
693+ return true ;
673694 }
674695 }
675696 }
@@ -711,26 +732,24 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
711732
712733 internal override int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) => serverSelectionStrategy . HashSlot ( key ) ;
713734
714- internal override bool TryValidate ( in RawResult result , out bool value )
735+ internal override bool TryValidate ( ref RespReader reader , out bool value )
715736 {
716- switch ( result . Resp2TypeBulkString )
737+ // LINDEX returns bulk string, simple string, or integer
738+ if ( reader . IsScalar )
717739 {
718- case ResultType . BulkString :
719- case ResultType . SimpleString :
720- case ResultType . Integer :
721- var parsed = result . AsRedisValue ( ) ;
722- if ( expectedValue . HasValue )
723- {
724- value = ( parsed == expectedValue . Value ) == expectedResult ;
725- ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsed + "; expected: " + ( string ? ) expectedValue . Value +
726- "; wanted: " + ( expectedResult ? "==" : "!=" ) + "; voting: " + value ) ;
727- }
728- else
729- {
730- value = parsed . IsNull != expectedResult ;
731- ConnectionMultiplexer . TraceWithoutContext ( "exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value ) ;
732- }
733- return true ;
740+ var parsed = reader . ReadRedisValue ( ) ;
741+ if ( expectedValue . HasValue )
742+ {
743+ value = ( parsed == expectedValue . Value ) == expectedResult ;
744+ ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsed + "; expected: " + ( string ? ) expectedValue . Value +
745+ "; wanted: " + ( expectedResult ? "==" : "!=" ) + "; voting: " + value ) ;
746+ }
747+ else
748+ {
749+ value = parsed . IsNull != expectedResult ;
750+ ConnectionMultiplexer . TraceWithoutContext ( "exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value ) ;
751+ }
752+ return true ;
734753 }
735754 value = false ;
736755 return false ;
@@ -784,18 +803,15 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
784803
785804 internal override int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) => serverSelectionStrategy . HashSlot ( key ) ;
786805
787- internal override bool TryValidate ( in RawResult result , out bool value )
806+ internal override bool TryValidate ( ref RespReader reader , out bool value )
788807 {
789- switch ( result . Resp2TypeBulkString )
808+ // Length commands (HLEN, SCARD, LLEN, ZCARD, XLEN, STRLEN) return integer
809+ if ( reader . IsScalar && reader . TryReadInt64 ( out var parsed ) )
790810 {
791- case ResultType . BulkString :
792- case ResultType . SimpleString :
793- case ResultType . Integer :
794- var parsed = result . AsRedisValue ( ) ;
795- value = parsed . IsInteger && ( expectedLength . CompareTo ( ( long ) parsed ) == compareToResult ) ;
796- ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsed + "; expected: " + expectedLength +
797- "; wanted: " + GetComparisonString ( ) + "; voting: " + value ) ;
798- return true ;
811+ value = expectedLength . CompareTo ( parsed ) == compareToResult ;
812+ ConnectionMultiplexer . TraceWithoutContext ( "actual: " + parsed + "; expected: " + expectedLength +
813+ "; wanted: " + GetComparisonString ( ) + "; voting: " + value ) ;
814+ return true ;
799815 }
800816 value = false ;
801817 return false ;
@@ -841,18 +857,16 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
841857
842858 internal override int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) => serverSelectionStrategy . HashSlot ( key ) ;
843859
844- internal override bool TryValidate ( in RawResult result , out bool value )
860+ internal override bool TryValidate ( ref RespReader reader , out bool value )
845861 {
846- switch ( result . Resp2TypeBulkString )
862+ // Length commands (HLEN, SCARD, LLEN, ZCARD, XLEN, STRLEN) return integer
863+ if ( reader . IsScalar )
847864 {
848- case ResultType . BulkString :
849- case ResultType . SimpleString :
850- case ResultType . Integer :
851- var parsed = result . AsRedisValue ( ) ;
852- value = parsed . IsInteger && ( expectedLength . CompareTo ( ( long ) parsed ) == compareToResult ) ;
853- ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsed + "; expected: " + expectedLength +
854- "; wanted: " + GetComparisonString ( ) + "; voting: " + value ) ;
855- return true ;
865+ var parsed = reader . ReadRedisValue ( ) ;
866+ value = parsed . IsInteger && ( expectedLength . CompareTo ( ( long ) parsed ) == compareToResult ) ;
867+ ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsed + "; expected: " + expectedLength +
868+ "; wanted: " + GetComparisonString ( ) + "; voting: " + value ) ;
869+ return true ;
856870 }
857871 value = false ;
858872 return false ;
@@ -898,17 +912,16 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
898912
899913 internal override int GetHashSlot ( ServerSelectionStrategy serverSelectionStrategy ) => serverSelectionStrategy . HashSlot ( key ) ;
900914
901- internal override bool TryValidate ( in RawResult result , out bool value )
915+ internal override bool TryValidate ( ref RespReader reader , out bool value )
902916 {
903- switch ( result . Resp2TypeBulkString )
917+ // ZCOUNT returns integer
918+ if ( reader . IsScalar )
904919 {
905- case ResultType . Integer :
906- var parsedValue = result . AsRedisValue ( ) ;
907- value = ( parsedValue == expectedValue ) == expectedEqual ;
908- ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsedValue + "; expected: " + ( string ? ) expectedValue + "; wanted: " + ( expectedEqual ? "==" : "!=" ) + "; voting: " + value ) ;
909- return true ;
920+ var parsedValue = reader . ReadRedisValue ( ) ;
921+ value = ( parsedValue == expectedValue ) == expectedEqual ;
922+ ConnectionMultiplexer . TraceWithoutContext ( "actual: " + ( string ? ) parsedValue + "; expected: " + ( string ? ) expectedValue + "; wanted: " + ( expectedEqual ? "==" : "!=" ) + "; voting: " + value ) ;
923+ return true ;
910924 }
911-
912925 value = false ;
913926 return false ;
914927 }
0 commit comments