@@ -11,13 +11,26 @@ public struct MySQLDataEncoder {
1111 if let custom = value as? MySQLDataConvertible , let data = custom. mysqlData {
1212 return data
1313 } else {
14- let encoder = _Encoder ( )
15- try value. encode ( to: encoder)
16- if let data = encoder. data {
17- return data
18- } else {
14+ let encoder = _Encoder ( parent: self )
15+ do {
16+ try value. encode ( to: encoder)
17+ if let value = encoder. value {
18+ return value
19+ } else {
20+ throw _Encoder. NonScalarValueSentinel ( )
21+ }
22+ } catch is _Encoder . NonScalarValueSentinel {
1923 var buffer = ByteBufferAllocator ( ) . buffer ( capacity: 0 )
20- try buffer. writeBytes ( self . json. encode ( _Wrapper ( value) ) )
24+ #if swift(<5.7)
25+ struct _Wrapper : Encodable {
26+ let encodable : Encodable
27+ init ( _ encodable: Encodable ) { self . encodable = encodable }
28+ func encode( to encoder: Encoder ) throws { try self . encodable. encode ( to: encoder) }
29+ }
30+ try buffer. writeBytes ( self . json. encode ( _Wrapper ( value) ) ) // Swift <5.7 will complain that "Encodable does not conform to Encodable" without the wrapper
31+ #else
32+ try buffer. writeBytes ( self . json. encode ( value) )
33+ #endif
2134 return MySQLData (
2235 type: . string,
2336 format: . text,
@@ -27,145 +40,50 @@ public struct MySQLDataEncoder {
2740 }
2841 }
2942 }
30-
43+
3144 private final class _Encoder : Encoder {
32- var codingPath : [ CodingKey ] {
33- return [ ]
34- }
35-
36- var userInfo : [ CodingUserInfoKey : Any ] {
37- return [ : ]
38- }
39- var data : MySQLData ?
40- init ( ) {
45+ struct NonScalarValueSentinel : Error { }
4146
42- }
43-
44- func container< Key> ( keyedBy type: Key . Type ) -> KeyedEncodingContainer < Key > where Key : CodingKey {
45- return . init( _KeyedValueEncoder ( self ) )
46- }
47-
48- func unkeyedContainer( ) -> UnkeyedEncodingContainer {
49- _UnkeyedEncoder ( self )
50- }
47+ var userInfo : [ CodingUserInfoKey : Any ] { [ : ] } ; var codingPath : [ CodingKey ] { [ ] }
48+ var parent : MySQLDataEncoder , value : MySQLData ?
5149
50+ init ( parent: MySQLDataEncoder ) { self . parent = parent }
51+ func container< K: CodingKey > ( keyedBy: K . Type ) -> KeyedEncodingContainer < K > { . init( _FailingKeyedContainer ( ) ) }
52+ func unkeyedContainer( ) -> UnkeyedEncodingContainer { _TaintedEncoder ( ) }
5253 func singleValueContainer( ) -> SingleValueEncodingContainer {
53- _SingleValueEncoder ( self )
54- }
55- }
56-
57- struct DoJSON : Error { }
58-
59- private struct _UnkeyedEncoder : UnkeyedEncodingContainer {
60- var codingPath : [ CodingKey ] {
61- self . encoder. codingPath
62- }
63- var count : Int {
64- 0
65- }
66-
67- let encoder : _Encoder
68- init ( _ encoder: _Encoder ) {
69- self . encoder = encoder
70- }
71-
72-
73- mutating func encodeNil( ) throws { }
74-
75- mutating func encode< T> ( _ value: T ) throws
76- where T : Encodable
77- { }
78-
79- mutating func nestedContainer< NestedKey> (
80- keyedBy keyType: NestedKey . Type
81- ) -> KeyedEncodingContainer < NestedKey >
82- where NestedKey : CodingKey
83- {
84- self . encoder. container ( keyedBy: NestedKey . self)
85- }
86-
87- mutating func nestedUnkeyedContainer( ) -> UnkeyedEncodingContainer {
88- self . encoder. unkeyedContainer ( )
89- }
90-
91- mutating func superEncoder( ) -> Encoder {
92- self . encoder
54+ precondition ( self . value == nil , " Requested multiple containers from the same encoder. " )
55+ return _SingleValueContainer ( encoder: self )
9356 }
94- }
95-
96- private struct _KeyedValueEncoder < Key> : KeyedEncodingContainerProtocol where Key: CodingKey {
97- var codingPath : [ CodingKey ] {
98- return self . encoder. codingPath
99- }
100-
101- let encoder : _Encoder
102- init ( _ encoder: _Encoder ) {
103- self . encoder = encoder
104- }
105-
106- mutating func encodeNil( forKey key: Key ) throws { }
107-
108- mutating func encode< T> ( _ value: T , forKey key: Key ) throws
109- where T : Encodable
110- { }
11157
112- mutating func nestedContainer< NestedKey> (
113- keyedBy keyType: NestedKey . Type ,
114- forKey key: Key
115- ) -> KeyedEncodingContainer < NestedKey > where NestedKey : CodingKey {
116- self . encoder. container ( keyedBy: NestedKey . self)
58+ struct _SingleValueContainer : SingleValueEncodingContainer {
59+ let encoder : _Encoder ; var codingPath : [ CodingKey ] { self . encoder. codingPath }
60+ func encodeNil( ) throws { self . encoder. value = . null }
61+ func encode< T: Encodable > ( _ value: T ) throws { self . encoder. value = try self . encoder. parent. encode ( value) }
11762 }
11863
119- mutating func nestedUnkeyedContainer( forKey key: Key ) -> UnkeyedEncodingContainer {
120- self . encoder. unkeyedContainer ( )
64+ /// This pair of types is only necessary because we can't directly throw an error from various Encoder and
65+ /// encoding container methods. We define duplicate types rather than the old implementation's use of a
66+ /// no-action keyed container because it can save a significant amount of time otherwise spent uselessly calling
67+ /// nested methods in some cases.
68+ struct _TaintedEncoder : Encoder , UnkeyedEncodingContainer , SingleValueEncodingContainer {
69+ var userInfo : [ CodingUserInfoKey : Any ] { [ : ] } ; var codingPath : [ CodingKey ] { [ ] } ; var count : Int { 0 }
70+ func container< K: CodingKey > ( keyedBy: K . Type ) -> KeyedEncodingContainer < K > { . init( _FailingKeyedContainer ( ) ) }
71+ func nestedContainer< K: CodingKey > ( keyedBy: K . Type ) -> KeyedEncodingContainer < K > { . init( _FailingKeyedContainer ( ) ) }
72+ func unkeyedContainer( ) -> UnkeyedEncodingContainer { self }
73+ func nestedUnkeyedContainer( ) -> UnkeyedEncodingContainer { self }
74+ func singleValueContainer( ) -> SingleValueEncodingContainer { self }
75+ func superEncoder( ) -> Encoder { self }
76+ func encodeNil( ) throws { throw NonScalarValueSentinel ( ) }
77+ func encode< T: Encodable > ( _: T ) throws { throw NonScalarValueSentinel ( ) }
78+ }
79+ struct _FailingKeyedContainer < K: CodingKey > : KeyedEncodingContainerProtocol {
80+ var codingPath : [ CodingKey ] { [ ] }
81+ func encodeNil( forKey: K ) throws { throw NonScalarValueSentinel ( ) }
82+ func encode< T: Encodable > ( _: T , forKey: K ) throws { throw NonScalarValueSentinel ( ) }
83+ func nestedContainer< NK: CodingKey > ( keyedBy: NK . Type , forKey: K ) -> KeyedEncodingContainer < NK > { . init( _FailingKeyedContainer < NK > ( ) ) }
84+ func nestedUnkeyedContainer( forKey: K ) -> UnkeyedEncodingContainer { _TaintedEncoder ( ) }
85+ func superEncoder( ) -> Encoder { _TaintedEncoder ( ) }
86+ func superEncoder( forKey: K ) -> Encoder { _TaintedEncoder ( ) }
12187 }
122-
123- mutating func superEncoder( ) -> Encoder {
124- self . encoder
125- }
126-
127- mutating func superEncoder( forKey key: Key ) -> Encoder {
128- self . encoder
129- }
130- }
131-
132-
133- private struct _SingleValueEncoder : SingleValueEncodingContainer {
134- var codingPath : [ CodingKey ] {
135- return self . encoder. codingPath
136- }
137-
138- let encoder : _Encoder
139- init ( _ encoder: _Encoder ) {
140- self . encoder = encoder
141- }
142-
143- mutating func encodeNil( ) throws {
144- self . encoder. data = MySQLData . null
145- }
146-
147- mutating func encode< T> ( _ value: T ) throws where T : Encodable {
148- if let convertible = value as? MySQLDataConvertible {
149- guard let data = convertible. mysqlData else {
150- throw EncodingError . invalidValue ( convertible, EncodingError . Context (
151- codingPath: self . codingPath,
152- debugDescription: " Could not encode \( T . self) to MySQL data: \( value) "
153- ) )
154- }
155- self . encoder. data = data
156- } else {
157- try value. encode ( to: self . encoder)
158- }
159- }
160- }
161- }
162-
163- struct _Wrapper : Encodable {
164- let encodable : Encodable
165- init ( _ encodable: Encodable ) {
166- self . encodable = encodable
167- }
168- func encode( to encoder: Encoder ) throws {
169- try self . encodable. encode ( to: encoder)
17088 }
17189}
0 commit comments