@@ -130,6 +130,107 @@ class ObjectSerializer {
130130 return try customDecoder. decode ( type, from: data) ;
131131 }
132132
133+ // Deserialize an multipart response
134+ public static func parseMultipart( data: Data ) throws -> [ ResponseFormParam ] {
135+ var result = [ ResponseFormParam] ( ) ;
136+ if ( !data. starts ( with: " -- " . data ( using: . utf8) !) ) {
137+ throw WordsApiError . invalidMultipartResponse ( message: " Boundary not found " ) ;
138+ }
139+
140+ let newLineData = " \r \n " . data ( using: . utf8) !;
141+ let boundaryEndIndex = data. range ( of: newLineData) ;
142+ if ( boundaryEndIndex == nil || boundaryEndIndex!. isEmpty) {
143+ throw WordsApiError . invalidMultipartResponse ( message: " Boundary not found " ) ;
144+ }
145+
146+ let boundary = data. subdata ( in: data. startIndex..< boundaryEndIndex!. lowerBound) ;
147+ let parts = ObjectSerializer . splitData ( data: data, separator: boundary) ;
148+ let dispositionSeparator = " \r \n \r \n " . data ( using: . utf8) !;
149+
150+ for part in parts {
151+ let partDataBounds = part. range ( of: dispositionSeparator) ;
152+ if ( partDataBounds == nil || partDataBounds!. isEmpty) {
153+ throw WordsApiError . invalidMultipartResponse ( message: " Part content not found " ) ;
154+ }
155+
156+ let headData = part. subdata ( in: part. startIndex..< partDataBounds!. lowerBound) ;
157+ let headContent = String ( decoding: headData, as: UTF8 . self) ;
158+ var headers = [ String : String] ( ) ;
159+
160+ for headerRawData in headContent. components ( separatedBy: " \r \n " ) {
161+ let headerData = headerRawData. trimmingCharacters ( in: . whitespacesAndNewlines) ;
162+ if ( !headerData. isEmpty) {
163+ let headerParts = headerData. split ( separator: " : " ) ;
164+ if ( headerParts. count == 2 ) {
165+ let headerKey = headerParts [ 0 ] . trimmingCharacters ( in: . whitespaces) ;
166+ let headerValue = headerParts [ 1 ] . trimmingCharacters ( in: . whitespaces) ;
167+ headers [ headerKey] = headerValue;
168+ }
169+ }
170+ }
171+
172+ let bodyData = part. subdata ( in: partDataBounds!. upperBound..< part. endIndex) ;
173+ result. append ( ResponseFormParam ( body: bodyData, headers: headers) ) ;
174+ }
175+
176+ return result;
177+ }
178+
179+ // Split data into parts
180+ public static func splitData( data: Data , separator: Data ) -> [ Data ] {
181+ let endIndex = separator. count;
182+ var chunks : [ Data ] = [ ] ;
183+ var pos = 0 ;
184+ while let r = data [ pos... ] . range ( of: separator) {
185+ if ( r. lowerBound > pos) {
186+ chunks. append ( data [ pos..< r. lowerBound] ) ;
187+ }
188+
189+ pos = r. upperBound;
190+ }
191+
192+ if ( pos < endIndex) {
193+ chunks. append ( data [ pos..< endIndex] ) ;
194+ }
195+
196+ return chunks;
197+ }
198+
199+ // Create an instance of T, from batch part data
200+ public static func deserializeBatchPart( request: WordsApiRequest , partData: ResponseFormParam ) throws -> Any ? {
201+ let separator = " \r \n \r \n " . data ( using: . utf8) !;
202+ let data = partData. getBody ( ) ;
203+ let partDataBounds = data. range ( of: separator) ;
204+ if ( partDataBounds == nil || partDataBounds!. isEmpty) {
205+ throw WordsApiError . invalidMultipartResponse ( message: " Body content not found " ) ;
206+ }
207+
208+ let headData = data. subdata ( in: data. startIndex..< partDataBounds!. lowerBound) ;
209+ let headContent = String ( decoding: headData, as: UTF8 . self) ;
210+ let headParts = headContent. components ( separatedBy: " \r \n " ) ;
211+ if ( headParts. count == 0 ) {
212+ throw WordsApiError . invalidMultipartResponse ( message: " Head content not found " ) ;
213+ }
214+
215+ let codeContent = headParts [ 0 ] . split ( separator: " " , maxSplits: 1 , omittingEmptySubsequences: true ) ;
216+ if ( codeContent. count != 2 ) {
217+ throw WordsApiError . invalidMultipartResponse ( message: " Head content not found " ) ;
218+ }
219+
220+ let codeStatus = Int ( codeContent [ 0 ] ) ;
221+ if ( codeStatus == nil ) {
222+ throw WordsApiError . invalidMultipartResponse ( message: " Failed to parse head content " ) ;
223+ }
224+
225+ let bodyData = data. subdata ( in: partDataBounds!. upperBound..< data. endIndex) ;
226+ if ( codeStatus != 200 ) {
227+ let errorMessage = String ( decoding: bodyData, as: UTF8 . self) ;
228+ return WordsApiError . requestError ( errorCode: codeStatus!, message: errorMessage) ;
229+ }
230+
231+ return try request. deserializeResponse ( data: bodyData) ;
232+ }
233+
133234 // Configuration for DateTime serialization/deserialization
134235 public static let customIso8601 : DateFormatter = {
135236 let formatter = DateFormatter ( )
0 commit comments