1212//
1313//===----------------------------------------------------------------------===//
1414
15+ /// Error thrown from parsing URLEncoded forms
16+ public struct URLEncodedFormError : Error , CustomStringConvertible {
17+ public struct Code : Sendable , Equatable {
18+ fileprivate enum Internal : Equatable {
19+ case duplicateKeys
20+ case addingToInvalidType
21+ case failedToPercentDecode
22+ case corruptKeyValue
23+ case notSupported
24+ case invalidArrayIndex
25+ case unexpectedError
26+ }
27+ fileprivate let value : Internal
28+
29+ /// encoded form has duplicate keys in it
30+ public static var duplicateKeys : Self { . init( value: . duplicateKeys) }
31+ /// trying to add an array or dictionary value to something isnt an array of dictionary
32+ public static var addingToInvalidType : Self { . init( value: . addingToInvalidType) }
33+ /// failed to percent decode key or value
34+ public static var failedToPercentDecode : Self { . init( value: . failedToPercentDecode) }
35+ /// corrupt dictionary key in form data
36+ public static var corruptKeyValue : Self { . init( value: . corruptKeyValue) }
37+ /// Form structure not supported eg arrays of arrays
38+ public static var notSupported : Self { . init( value: . notSupported) }
39+ /// Array includes an invalid array index
40+ public static var invalidArrayIndex : Self { . init( value: . invalidArrayIndex) }
41+ /// Unexpected errpr
42+ public static var unexpectedError : Self { . init( value: . unexpectedError) }
43+ }
44+
45+ public let code : Code
46+ public let value : String
47+
48+ init ( code: Code , value: String ) {
49+ self . code = code
50+ self . value = value
51+ }
52+
53+ init ( code: Code , value: Substring ) {
54+ self . code = code
55+ self . value = . init( value)
56+ }
57+ }
58+
59+ extension URLEncodedFormError {
60+ public var description : String {
61+ switch self . code. value {
62+ case . duplicateKeys: " Found duplicate keys with name ' \( self . value) ' "
63+ case . addingToInvalidType: " Adding array or dictionary value to non array or dictionary value ' \( self . value) ' "
64+ case . failedToPercentDecode: " Failed to percent decode ' \( self . value) ' "
65+ case . corruptKeyValue: " Parsing dictionary key value failed ' \( self . value) ' "
66+ case . notSupported: " URLEncoded form structure not supported ' \( self . value) ' "
67+ case . invalidArrayIndex: " Invalid array index ' \( self . value) ' "
68+ case . unexpectedError:
69+ " Unexpected error with ' \( self . value) ' please add an issue at https://github.com/hummingbird-project/hummingbird/issues "
70+ }
71+ }
72+ }
1573/// Internal representation of URL encoded form data used by both encode and decode
1674enum URLEncodedFormNode : CustomStringConvertible , Equatable {
1775 /// holds a value
@@ -20,12 +78,8 @@ enum URLEncodedFormNode: CustomStringConvertible, Equatable {
2078 case map( Map )
2179 /// holds an array of nodes
2280 case array( Array )
23-
24- enum Error : Swift . Error , Equatable {
25- case failedToDecode( String ? = nil )
26- case notSupported
27- case invalidArrayIndex( Int )
28- }
81+ // empty node
82+ case empty
2983
3084 /// Initialize node from URL encoded form data
3185 /// - Parameter string: URL encoded form data
@@ -47,12 +101,14 @@ enum URLEncodedFormNode: CustomStringConvertible, Equatable {
47101 let before = element [ ..< equals] . removingURLPercentEncoding ( )
48102 let afterEquals = element. index ( after: equals)
49103 let after = element [ afterEquals... ] . replacingOccurrences ( of: " + " , with: " " )
50- guard let key = before else { throw Error . failedToDecode ( " Failed to percent decode \( element) " ) }
104+ guard let key = before else { throw URLEncodedFormError ( code : . failedToPercentDecode , value : element [ ..< equals ] ) }
51105
52- guard let keys = KeyParser . parse ( key) else { throw Error . failedToDecode ( " Unexpected key value " ) }
53- guard let value = NodeValue ( percentEncoded: after) else { throw Error . failedToDecode ( " Failed to percent decode \( after) " ) }
106+ guard let keys = KeyParser . parse ( key) else { throw URLEncodedFormError ( code: . corruptKeyValue, value: key) }
107+ guard let value = NodeValue ( percentEncoded: after) else {
108+ throw URLEncodedFormError ( code: . failedToPercentDecode, value: after)
109+ }
54110
55- try node. addValue ( keys: keys [ ... ] , value: value)
111+ try node. addValue ( keys: keys [ ... ] , value: value, key : key )
56112 }
57113 }
58114 return node
@@ -62,7 +118,7 @@ enum URLEncodedFormNode: CustomStringConvertible, Equatable {
62118 /// - Parameters:
63119 /// - keys: Array of key parser types (array or map)
64120 /// - value: value to add to leaf node
65- private func addValue( keys: ArraySlice < KeyParser . KeyType > , value: NodeValue ) throws {
121+ private func addValue( keys: ArraySlice < KeyParser . KeyType > , value: NodeValue , key : String ) throws {
66122 /// function for create `URLEncodedFormNode` from `KeyParser.Key.Type`
67123 func createNode( from key: KeyParser . KeyType ) -> URLEncodedFormNode {
68124 switch key {
@@ -81,31 +137,35 @@ enum URLEncodedFormNode: CustomStringConvertible, Equatable {
81137 case ( . map( let map) , . map( let key) ) :
82138 let key = String ( key)
83139 if keys. count == 0 {
84- guard map. values [ key] == nil else { throw Error . failedToDecode ( ) }
140+ guard map. values [ key] == nil else { throw URLEncodedFormError ( code : . duplicateKeys , value : key ) }
85141 map. values [ key] = . leaf( value)
86142 } else {
87143 if let node = map. values [ key] {
88- try node. addValue ( keys: keys, value: value)
144+ try node. addValue ( keys: keys, value: value, key : key )
89145 } else {
90146 let node = createNode ( from: keys. first!)
91147 map. values [ key] = node
92- try node. addValue ( keys: keys, value: value)
148+ try node. addValue ( keys: keys, value: value, key : key )
93149 }
94150 }
95151 case ( . array( let array) , . array) :
96152 if keys. count == 0 {
97153 array. values. append ( . leaf( value) )
98154 } else {
99155 // currently don't support arrays and maps inside arrays
100- throw Error . notSupported
156+ throw URLEncodedFormError ( code : . notSupported, value : key )
101157 }
102158 case ( . array( let array) , . arrayWithIndices( let index) ) :
103159 guard keys. count == 0 , array. values. count == index else {
104- throw Error . invalidArrayIndex ( index)
160+ throw URLEncodedFormError ( code : . invalidArrayIndex, value : " \( key ) [ \( index) ] " )
105161 }
106162 array. values. append ( . leaf( value) )
163+ case ( _, . arrayWithIndices) , ( _, . array) :
164+ throw URLEncodedFormError ( code: . addingToInvalidType, value: key)
165+ case ( _, . map) :
166+ throw URLEncodedFormError ( code: . addingToInvalidType, value: key)
107167 default :
108- throw Error . failedToDecode ( )
168+ throw URLEncodedFormError ( code : . unexpectedError , value : key )
109169 }
110170 }
111171
@@ -130,6 +190,8 @@ enum URLEncodedFormNode: CustomStringConvertible, Equatable {
130190 $0. value. encode ( " \( prefix) [ \( $0. key) ] " )
131191 } . joined ( separator: " & " )
132192 }
193+ case . empty:
194+ return " "
133195 }
134196 }
135197
0 commit comments