@@ -285,18 +285,18 @@ public static Condition StringNotEqual(RedisKey key, RedisValue value)
285285 public static Condition SortedSetNotContains ( RedisKey key , RedisValue member ) => new ExistsCondition ( key , RedisType . SortedSet , member , false ) ;
286286
287287 /// <summary>
288- /// Enforces that the given sorted set contains a member that ist starting with the start-sequence .
288+ /// Enforces that the given sorted set contains a member that starts with the specified prefix .
289289 /// </summary>
290290 /// <param name="key">The key of the sorted set to check.</param>
291- /// <param name="memberStartSequence">a byte array: the set must contain at least one member, that starts with the byte-sequence .</param>
292- public static Condition SortedSetStartsWith ( RedisKey key , byte [ ] memberStartSequence ) => new StartsWithCondition ( key , memberStartSequence , true ) ;
291+ /// <param name="prefix">The sorted set must contain at least one member that starts with the specified prefix .</param>
292+ public static Condition SortedSetContainsStarting ( RedisKey key , RedisValue prefix ) => new StartsWithCondition ( key , prefix , true ) ;
293293
294294 /// <summary>
295- /// Enforces that the given sorted set does not contain a member that ist starting with the start-sequence .
295+ /// Enforces that the given sorted set does not contain a member that starts with the specified prefix .
296296 /// </summary>
297297 /// <param name="key">The key of the sorted set to check.</param>
298- /// <param name="memberStartSequence">a byte array: the set must not contain any members, that start with the byte-sequence .</param>
299- public static Condition SortedSetNotStartsWith ( RedisKey key , byte [ ] memberStartSequence ) => new StartsWithCondition ( key , memberStartSequence , false ) ;
298+ /// <param name="prefix">The sorted set must not contain at a member that starts with the specified prefix .</param>
299+ public static Condition SortedSetNotContainsStarting ( RedisKey key , RedisValue prefix ) => new StartsWithCondition ( key , prefix , false ) ;
300300
301301 /// <summary>
302302 /// Enforces that the given sorted set member must have the specified score.
@@ -541,35 +541,45 @@ internal sealed class StartsWithCondition : Condition
541541 working with byte arrays should prevent any encoding within this class, that could distort the comparison */
542542
543543 private readonly bool expectedResult ;
544- private readonly RedisValue expectedStartValue ;
544+ private readonly RedisValue prefix ;
545545 private readonly RedisKey key ;
546546
547547 internal override Condition MapKeys ( Func < RedisKey , RedisKey > map ) =>
548- new StartsWithCondition ( map ( key ) , expectedStartValue , expectedResult ) ;
548+ new StartsWithCondition ( map ( key ) , prefix , expectedResult ) ;
549549
550- public StartsWithCondition ( in RedisKey key , in RedisValue expectedStartValue , bool expectedResult )
550+ public StartsWithCondition ( in RedisKey key , in RedisValue prefix , bool expectedResult )
551551 {
552552 if ( key . IsNull ) throw new ArgumentNullException ( nameof ( key ) ) ;
553- if ( expectedStartValue . IsNull ) throw new ArgumentNullException ( nameof ( expectedStartValue ) ) ;
553+ if ( prefix . IsNull ) throw new ArgumentNullException ( nameof ( prefix ) ) ;
554554 this . key = key ;
555- this . expectedStartValue = expectedStartValue ; // array with length 0 returns true condition
555+ this . prefix = prefix ;
556556 this . expectedResult = expectedResult ;
557557 }
558558
559559 public override string ToString ( ) =>
560- ( expectedStartValue . IsNull ? key . ToString ( ) : ( ( string ? ) key ) + " " + RedisType . SortedSet + " > " + expectedStartValue )
561- + ( expectedResult ? " starts with" : " does not start with" ) ;
560+ $ "{ key } { nameof ( RedisType . SortedSet ) } > { ( expectedResult ? " member starting " : " no member starting " ) } { prefix } + prefix";
562561
563562 internal override void CheckCommands ( CommandMap commandMap ) => commandMap . AssertAvailable ( RedisCommand . ZRANGEBYLEX ) ;
564563
565564 internal override IEnumerable < Message > CreateMessages ( int db , IResultBox ? resultBox )
566565 {
567566 yield return Message . Create ( db , CommandFlags . None , RedisCommand . WATCH , key ) ;
568567
569- #pragma warning disable CS8600 , CS8604 , SA1117 // expectedStartValue is checked to be not null in Constructor and must be a byte[] because of API-parameters
570- var message = ConditionProcessor . CreateMessage ( this , db , CommandFlags . None , RedisCommand . ZRANGEBYLEX , key ,
571- CombineBytes ( 91 , ( byte [ ] ) expectedStartValue . Box ( ) ) , "+" , "LIMIT" , "0" , "1" ) ; // prepends '[' to startValue for inclusive search in CombineBytes
572- #pragma warning disable CS8600 , CS8604 , SA1117
568+ // prepend '[' to prefix for inclusive search
569+ var startValueWithToken = RedisDatabase . GetLexRange ( prefix , Exclude . None , isStart : true , Order . Ascending ) ;
570+
571+ var message = ConditionProcessor . CreateMessage (
572+ this ,
573+ db ,
574+ CommandFlags . None ,
575+ RedisCommand . ZRANGEBYLEX ,
576+ key ,
577+ startValueWithToken ,
578+ RedisLiterals . PlusSymbol ,
579+ RedisLiterals . LIMIT ,
580+ 0 ,
581+ 1 ) ;
582+
573583 message . SetSource ( ConditionProcessor . Default , resultBox ) ;
574584 yield return message ;
575585 }
@@ -578,39 +588,9 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
578588
579589 internal override bool TryValidate ( in RawResult result , out bool value )
580590 {
581- RedisValue [ ] ? r = result . GetItemsAsValues ( ) ;
582- if ( result . ItemsCount == 0 ) value = false ; // false, if empty list -> read after end of memberlist / itemsCout > 1 is impossible due to 'LIMIT 0 1'
583- #pragma warning disable CS8600 , CS8604 // warnings on StartsWith can be ignored because of ItemsCount-check in then preceding command!!
584- else value = r != null && r . Length > 0 && StartsWith ( ( byte [ ] ) r [ 0 ] . Box ( ) , expectedStartValue ) ;
585- #pragma warning disable CS8600 , CS8604
591+ value = result . ItemsCount == 1 && result [ 0 ] . AsRedisValue ( ) . StartsWith ( prefix ) ;
586592
587- #pragma warning disable CS8602 // warning for r[0] can be ignored because of null-check in then same command-line !!
588593 if ( ! expectedResult ) value = ! value ;
589- ConnectionMultiplexer . TraceWithoutContext ( "actual: " + r == null ? "null" : r . Length == 0 ? "empty" : r [ 0 ] . ToString ( )
590- + "; expected: " + expectedStartValue . ToString ( )
591- + "; wanted: " + ( expectedResult ? "StartsWith" : "NotStartWith" )
592- + "; voting: " + value ) ;
593- #pragma warning restore CS8602
594- return true ;
595- }
596-
597- private static byte [ ] CombineBytes ( byte b1 , byte [ ] a1 ) // combines b1 and a1 to new array
598- {
599- byte [ ] newArray = new byte [ a1 . Length + 1 ] ;
600- newArray [ 0 ] = b1 ;
601- System . Buffer . BlockCopy ( a1 , 0 , newArray , 1 , a1 . Length ) ;
602- return newArray ;
603- }
604-
605- internal bool StartsWith ( byte [ ] result , byte [ ] searchfor )
606- {
607- if ( searchfor . Length > result . Length ) return false ;
608-
609- for ( int i = 0 ; i < searchfor . Length ; i ++ )
610- {
611- if ( result [ i ] != searchfor [ i ] ) return false ;
612- }
613-
614594 return true ;
615595 }
616596 }
0 commit comments