@@ -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.
@@ -611,28 +584,21 @@ public struct ValkeyClusterSlotRange: Hashable, Sendable, RESPTokenDecodable {
611584}
612585
613586extension ValkeyClusterDescription {
614- fileprivate static func makeClusterDescription( respToken: RESPToken ) throws ( ValkeyClusterParseError . Reason ) -> ValkeyClusterDescription {
587+ fileprivate static func makeClusterDescription( respToken: RESPToken ) throws ( RESPDecodeError ) -> ValkeyClusterDescription {
615588 guard case . array( let shardsToken) = respToken. value else {
616- throw . clusterDescriptionTokenIsNotAnArray
589+ throw RESPDecodeError . tokenMismatch ( expected : [ . array ] , token : respToken )
617590 }
618- let shards = try shardsToken. map { shardToken throws ( ValkeyClusterParseError . Reason ) in
591+ let shards = try shardsToken. map { shardToken throws ( RESPDecodeError ) in
619592 try ValkeyClusterDescription . Shard ( shardToken)
620593 }
621594 return ValkeyClusterDescription ( shards)
622595 }
623596}
624597
625598extension HashSlots {
626- fileprivate init ( _ iterator: inout RESPToken . Array . Iterator ) throws ( ValkeyClusterParseError. Reason) {
627- guard let token = iterator. next ( ) else {
628- throw . slotsTokenIsNotAnArray
629- }
630- self = try HashSlots ( token)
631- }
632-
633- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError. Reason) {
599+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError) {
634600 guard case . array( let array) = token. value else {
635- throw . slotsTokenIsNotAnArray
601+ throw RESPDecodeError . tokenMismatch ( expected : [ . array ] , token : token )
636602 }
637603
638604 var slotRanges = [ ClosedRange < HashSlot > ] ( )
@@ -648,31 +614,25 @@ extension HashSlots {
648614 slotRanges. append ( ClosedRange < HashSlot > ( uncheckedBounds: ( start, end) ) )
649615 }
650616
617+ if slotRanges. isEmpty { throw RESPDecodeError . invalidArraySize ( array, minExpectedSize: 1 ) }
651618 self = slotRanges
652619 }
653620}
654621
655622extension [ ValkeyClusterDescription . Node ] {
656- fileprivate init ( _ iterator: inout RESPToken . Array . Iterator ) throws ( ValkeyClusterParseError. Reason) {
657- guard let token = iterator. next ( ) else {
658- throw . nodesTokenIsNotAnArray
659- }
660- self = try Self ( token)
661- }
662-
663- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError. Reason) {
623+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError) {
664624 guard case . array( let array) = token. value else {
665- throw . nodesTokenIsNotAnArray
625+ throw RESPDecodeError . tokenMismatch ( expected : [ . array ] , token : token )
666626 }
667627
668- self = try array. map { token throws ( ValkeyClusterParseError . Reason ) in
628+ self = try array. map { token throws ( RESPDecodeError ) in
669629 try ValkeyClusterDescription . Node ( token)
670630 }
671631 }
672632}
673633
674634extension ValkeyClusterDescription . Shard {
675- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError . Reason ) {
635+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError ) {
676636 switch token. value {
677637 case . array( let array) :
678638 self = try Self . makeFromTokenSequence ( MapStyleArray ( underlying: array) )
@@ -688,13 +648,13 @@ extension ValkeyClusterDescription.Shard {
688648 self = try Self . makeFromTokenSequence ( mapped)
689649
690650 default :
691- throw ValkeyClusterParseError . Reason . shardTokenIsNotAnArrayOrMap
651+ throw RESPDecodeError . tokenMismatch ( expected : [ . array , . map ] , token : token )
692652 }
693653 }
694654
695655 fileprivate static func makeFromTokenSequence< TokenSequence: Sequence > (
696656 _ sequence: TokenSequence
697- ) throws ( ValkeyClusterParseError . Reason ) -> Self where TokenSequence. Element == ( String , RESPToken ) {
657+ ) throws ( RESPDecodeError ) -> Self where TokenSequence. Element == ( String , RESPToken ) {
698658 var slotRanges = HashSlots ( )
699659 var nodes : [ ValkeyClusterDescription . Node ] = [ ]
700660
@@ -711,18 +671,24 @@ extension ValkeyClusterDescription.Shard {
711671 }
712672 }
713673
714- if nodes. isEmpty { throw . shardIsMissingNode }
715- if slotRanges. isEmpty { throw . shardIsMissingHashSlots }
716-
717674 return . init( slots: slotRanges, nodes: nodes)
718675 }
719676}
720677
721678extension ValkeyClusterDescription . Node {
722- fileprivate init ( _ token: RESPToken ) throws ( ValkeyClusterParseError . Reason ) {
679+ fileprivate init ( _ token: RESPToken ) throws ( RESPDecodeError ) {
723680 switch token. value {
724681 case . array( let array) :
725- self = try Self . makeFromTokenSequence ( MapStyleArray ( underlying: array) )
682+ do {
683+ self = try Self . makeFromTokenSequence ( MapStyleArray ( underlying: array) )
684+ } catch {
685+ switch error {
686+ case . decodeError( let error) :
687+ throw error
688+ case . missingRequiredValue:
689+ throw RESPDecodeError ( . missingToken, token: token, message: " Missing required token for Node " )
690+ }
691+ }
726692
727693 case . map( let map) :
728694 let mapped = map. lazy. compactMap { ( keyNode, value) -> ( String , RESPToken ) ? in
@@ -732,16 +698,30 @@ extension ValkeyClusterDescription.Node {
732698 return nil
733699 }
734700 }
735- self = try Self . makeFromTokenSequence ( mapped)
701+ do {
702+ self = try Self . makeFromTokenSequence ( mapped)
703+ } catch {
704+ switch error {
705+ case . decodeError( let error) :
706+ throw error
707+ case . missingRequiredValue:
708+ throw RESPDecodeError ( . missingToken, token: token, message: " Missing required token for Node " )
709+ }
710+ }
736711
737712 default :
738- throw . nodeTokenIsNotAnArrayOrMap
713+ throw RESPDecodeError . tokenMismatch ( expected : [ . array , . map ] , token : token )
739714 }
740715 }
741716
717+ fileprivate enum TokenSequenceError : Error {
718+ case decodeError( RESPDecodeError )
719+ case missingRequiredValue
720+ }
721+
742722 fileprivate static func makeFromTokenSequence< TokenSequence: Sequence > (
743723 _ sequence: TokenSequence
744- ) throws ( ValkeyClusterParseError . Reason ) -> Self where TokenSequence. Element == ( String , RESPToken ) {
724+ ) throws ( TokenSequenceError ) -> Self where TokenSequence. Element == ( String , RESPToken ) {
745725 var id : String ?
746726 var port : Int64 ?
747727 var tlsPort : Int64 ?
@@ -769,7 +749,7 @@ extension ValkeyClusterDescription.Node {
769749 endpoint = try ? String ( fromRESP: nodeVal)
770750 case " role " :
771751 guard let roleString = try ? String ( fromRESP: nodeVal) , let roleValue = ValkeyClusterDescription . Node. Role ( rawValue: roleString) else {
772- throw . invalidNodeRole
752+ throw . decodeError ( RESPDecodeError ( . unexpectedToken , token : nodeVal , message : " Invalid Role String " ) )
773753 }
774754 role = roleValue
775755
@@ -779,7 +759,7 @@ extension ValkeyClusterDescription.Node {
779759 guard let healthString = try ? String ( fromRESP: nodeVal) ,
780760 let healthValue = ValkeyClusterDescription . Node. Health ( rawValue: healthString)
781761 else {
782- throw . invalidNodeHealth
762+ throw . decodeError ( RESPDecodeError ( . unexpectedToken , token : nodeVal , message : " Invalid Node Health String " ) )
783763 }
784764 health = healthValue
785765
@@ -791,12 +771,12 @@ extension ValkeyClusterDescription.Node {
791771 guard let id = id, let ip = ip, let endpoint = endpoint, let role = role,
792772 let replicationOffset = replicationOffset, let health = health
793773 else {
794- throw . missingRequiredValueForNode
774+ throw . missingRequiredValue
795775 }
796776
797777 // we need at least port or tlsport
798778 if port == nil && tlsPort == nil {
799- throw . missingRequiredValueForNode
779+ throw . missingRequiredValue
800780 }
801781
802782 return ValkeyClusterDescription . Node (
0 commit comments