@@ -35,29 +35,6 @@ extension CLUSTER.SLOTS {
3535 public typealias Response = [ ValkeyClusterSlotRange ]
3636}
3737
38- package struct ValkeyClusterParseError : Error , Equatable {
39- package enum Reason : Error {
40- case clusterDescriptionTokenIsNotAnArray
41- case shardTokenIsNotAnArrayOrMap
42- case nodesTokenIsNotAnArray
43- case nodeTokenIsNotAnArrayOrMap
44- case slotsTokenIsNotAnArray
45- case invalidNodeRole
46- case invalidNodeHealth
47- case missingRequiredValueForNode
48- case shardIsMissingHashSlots
49- case shardIsMissingNode
50- }
51-
52- package var reason : Reason
53- package var token : RESPToken
54-
55- package init ( reason: Reason , token: RESPToken ) {
56- self . reason = reason
57- self . token = token
58- }
59- }
60-
6138/// A description of a Valkey cluster.
6239///
6340/// A description is return when you call ``ValkeyClientProtocol/clusterShards()``.
@@ -204,11 +181,7 @@ public struct ValkeyClusterDescription: Hashable, Sendable, RESPTokenDecodable {
204181 /// Creates a cluster description from the response token you provide.
205182 /// - Parameter respToken: The response token.
206183 public init ( fromRESP respToken: RESPToken ) throws {
207- do {
208- self = try Self . makeClusterDescription ( respToken: respToken)
209- } catch {
210- throw ValkeyClusterParseError ( reason: error, token: respToken)
211- }
184+ self = try Self . makeClusterDescription ( respToken: respToken)
212185 }
213186
214187 /// Creates a cluster description from a list of shards you provide.
@@ -399,28 +372,28 @@ public struct ValkeyClusterSlotRange: Hashable, Sendable, RESPTokenDecodable {
399372}
400373
401374extension ValkeyClusterDescription {
402- fileprivate static func makeClusterDescription( respToken: RESPToken ) throws ( ValkeyClusterParseError . Reason ) -> ValkeyClusterDescription {
375+ fileprivate static func makeClusterDescription( respToken: RESPToken ) throws ( RESPDecodeError ) -> ValkeyClusterDescription {
403376 guard case . array( let shardsToken) = respToken. value else {
404- throw . clusterDescriptionTokenIsNotAnArray
377+ throw RESPDecodeError . tokenMismatch ( expected : [ . array ] , token : respToken )
405378 }
406- let shards = try shardsToken. map { shardToken throws ( ValkeyClusterParseError . Reason ) in
379+ let shards = try shardsToken. map { shardToken throws ( RESPDecodeError ) in
407380 try ValkeyClusterDescription . Shard ( shardToken)
408381 }
409382 return ValkeyClusterDescription ( shards)
410383 }
411384}
412385
413386extension HashSlots {
414- fileprivate init ( _ iterator: inout RESPToken . Array . Iterator ) throws ( ValkeyClusterParseError . Reason ) {
387+ fileprivate init ( _ iterator: inout RESPToken . Array . Iterator ) throws ( RESPDecodeError ) {
415388 guard let token = iterator. next ( ) else {
416- throw . slotsTokenIsNotAnArray
389+ throw RESPDecodeError ( . tokenMismatch , token : . null , message : " Expected to find an array token but reached end of input " )
417390 }
418391 self = try HashSlots ( token)
419392 }
420393
421- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError . Reason ) {
394+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError ) {
422395 guard case . array( let array) = token. value else {
423- throw . slotsTokenIsNotAnArray
396+ throw RESPDecodeError . tokenMismatch ( expected : [ . array ] , token : token )
424397 }
425398
426399 var slotRanges = [ ClosedRange < HashSlot > ] ( )
@@ -441,29 +414,29 @@ extension HashSlots {
441414}
442415
443416extension [ ValkeyClusterDescription . Node ] {
444- fileprivate init ( _ iterator: inout RESPToken . Array . Iterator ) throws ( ValkeyClusterParseError . Reason ) {
417+ fileprivate init ( _ iterator: inout RESPToken . Array . Iterator ) throws ( RESPDecodeError ) {
445418 guard let token = iterator. next ( ) else {
446- throw . nodesTokenIsNotAnArray
419+ throw RESPDecodeError ( . tokenMismatch , token : . null , message : " Expected to find an array token but reached end of input " )
447420 }
448421 self = try Self ( token)
449422 }
450423
451- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError . Reason ) {
424+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError ) {
452425 guard case . array( let array) = token. value else {
453- throw . nodesTokenIsNotAnArray
426+ throw RESPDecodeError . tokenMismatch ( expected : [ . array ] , token : token )
454427 }
455428
456- self = try array. map { token throws ( ValkeyClusterParseError . Reason ) in
429+ self = try array. map { token throws ( RESPDecodeError ) in
457430 try ValkeyClusterDescription . Node ( token)
458431 }
459432 }
460433}
461434
462435extension ValkeyClusterDescription . Shard {
463- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError . Reason ) {
436+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError ) {
464437 switch token. value {
465438 case . array( let array) :
466- self = try Self . makeFromTokenSequence ( MapStyleArray ( underlying: array) )
439+ self = try Self . makeFromTokenSequence ( MapStyleArray ( underlying: array) , token )
467440
468441 case . map( let map) :
469442 let mapped = map. lazy. compactMap { ( keyNode, value) -> ( String , RESPToken ) ? in
@@ -473,16 +446,17 @@ extension ValkeyClusterDescription.Shard {
473446 return nil
474447 }
475448 }
476- self = try Self . makeFromTokenSequence ( mapped)
449+ self = try Self . makeFromTokenSequence ( mapped, token )
477450
478451 default :
479- throw ValkeyClusterParseError . Reason . shardTokenIsNotAnArrayOrMap
452+ throw RESPDecodeError . tokenMismatch ( expected : [ . array , . map ] , token : token )
480453 }
481454 }
482455
483456 fileprivate static func makeFromTokenSequence< TokenSequence: Sequence > (
484- _ sequence: TokenSequence
485- ) throws ( ValkeyClusterParseError. Reason) -> Self where TokenSequence. Element == ( String , RESPToken ) {
457+ _ sequence: TokenSequence ,
458+ _ token: RESPToken
459+ ) throws ( RESPDecodeError) -> Self where TokenSequence. Element == ( String , RESPToken ) {
486460 var slotRanges = HashSlots ( )
487461 var nodes : [ ValkeyClusterDescription . Node ] = [ ]
488462
@@ -499,18 +473,18 @@ extension ValkeyClusterDescription.Shard {
499473 }
500474 }
501475
502- if nodes. isEmpty { throw . shardIsMissingNode }
503- if slotRanges. isEmpty { throw . shardIsMissingHashSlots }
476+ if nodes. isEmpty { throw RESPDecodeError . missingToken ( key : " nodes " , token : token ) }
477+ if slotRanges. isEmpty { throw RESPDecodeError . missingToken ( key : " shards " , token : token ) }
504478
505479 return . init( slots: slotRanges, nodes: nodes)
506480 }
507481}
508482
509483extension ValkeyClusterDescription . Node {
510- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError . Reason ) {
484+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError ) {
511485 switch token. value {
512486 case . array( let array) :
513- self = try Self . makeFromTokenSequence ( MapStyleArray ( underlying: array) )
487+ self = try Self . makeFromTokenSequence ( MapStyleArray ( underlying: array) , token )
514488
515489 case . map( let map) :
516490 let mapped = map. lazy. compactMap { ( keyNode, value) -> ( String , RESPToken ) ? in
@@ -520,16 +494,17 @@ extension ValkeyClusterDescription.Node {
520494 return nil
521495 }
522496 }
523- self = try Self . makeFromTokenSequence ( mapped)
497+ self = try Self . makeFromTokenSequence ( mapped, token )
524498
525499 default :
526- throw . nodeTokenIsNotAnArrayOrMap
500+ throw RESPDecodeError . tokenMismatch ( expected : [ . array , . map ] , token : token )
527501 }
528502 }
529503
530504 fileprivate static func makeFromTokenSequence< TokenSequence: Sequence > (
531- _ sequence: TokenSequence
532- ) throws ( ValkeyClusterParseError. Reason) -> Self where TokenSequence. Element == ( String , RESPToken ) {
505+ _ sequence: TokenSequence ,
506+ _ respToken: RESPToken
507+ ) throws ( RESPDecodeError) -> Self where TokenSequence. Element == ( String , RESPToken ) {
533508 var id : String ?
534509 var port : Int64 ?
535510 var tlsPort : Int64 ?
@@ -557,7 +532,7 @@ extension ValkeyClusterDescription.Node {
557532 endpoint = try ? String ( fromRESP: nodeVal)
558533 case " role " :
559534 guard let roleString = try ? String ( fromRESP: nodeVal) , let roleValue = ValkeyClusterDescription . Node. Role ( rawValue: roleString) else {
560- throw . invalidNodeRole
535+ throw RESPDecodeError . missingToken ( key : " role " , token : respToken )
561536 }
562537 role = roleValue
563538
@@ -567,7 +542,7 @@ extension ValkeyClusterDescription.Node {
567542 guard let healthString = try ? String ( fromRESP: nodeVal) ,
568543 let healthValue = ValkeyClusterDescription . Node. Health ( rawValue: healthString)
569544 else {
570- throw . invalidNodeHealth
545+ throw RESPDecodeError . missingToken ( key : " health " , token : respToken )
571546 }
572547 health = healthValue
573548
@@ -579,12 +554,12 @@ extension ValkeyClusterDescription.Node {
579554 guard let id = id, let ip = ip, let endpoint = endpoint, let role = role,
580555 let replicationOffset = replicationOffset, let health = health
581556 else {
582- throw . missingRequiredValueForNode
557+ throw RESPDecodeError . missingToken ( key : " id or ip or endpoint or role or replication-offset or health " , token : respToken )
583558 }
584559
585560 // we need at least port or tlsport
586561 if port == nil && tlsPort == nil {
587- throw . missingRequiredValueForNode
562+ throw RESPDecodeError . missingToken ( key : " port or tls-port " , token : respToken )
588563 }
589564
590565 return ValkeyClusterDescription . Node (
0 commit comments