@@ -181,6 +181,299 @@ mod decl {
181181 }
182182 Ok ( ( * c - 0x20 ) & 0x3f )
183183 }
184+ #[ derive( FromArgs ) ]
185+ struct A2bQpArgs {
186+ #[ pyarg( any) ]
187+ data : ArgAsciiBuffer ,
188+ #[ pyarg( named, default = "false" ) ]
189+ header : bool ,
190+ }
191+ #[ pyfunction]
192+ fn a2b_qp ( args : A2bQpArgs ) -> PyResult < Vec < u8 > > {
193+ let s = args. data ;
194+ let header = args. header ;
195+ s. with_ref ( |buffer| {
196+ let len = buffer. len ( ) ;
197+ let mut out_data = Vec :: < u8 > :: with_capacity ( len) ;
198+
199+ let mut idx = 0 ;
200+
201+ while idx < len {
202+ if buffer[ idx] == 0x3d {
203+ idx += 1 ;
204+ if idx >= len {
205+ break ;
206+ }
207+ /* Soft line breaks */
208+ if ( buffer[ idx] == 0x0a ) || ( buffer[ idx] == 0x0d ) {
209+ if buffer[ idx] != 0x0a {
210+ while idx < len && buffer[ idx] != 0x0a {
211+ idx += 1 ;
212+ }
213+ }
214+ if idx < len {
215+ idx += 1 ;
216+ }
217+ } else if buffer[ idx] == 0x3d {
218+ out_data. push ( 0x3d ) ;
219+ idx += 1 ;
220+ } else if idx + 1 < len
221+ && ( ( buffer[ idx] >= 0x41 && buffer[ idx] <= 0x46 )
222+ || ( buffer[ idx] >= 0x61 && buffer[ idx] <= 0x66 )
223+ || ( buffer[ idx] >= 0x30 && buffer[ idx] <= 0x39 ) )
224+ && ( ( buffer[ idx + 1 ] >= 0x41 && buffer[ idx + 1 ] <= 0x46 )
225+ || ( buffer[ idx + 1 ] >= 0x61 && buffer[ idx + 1 ] <= 0x66 )
226+ || ( buffer[ idx + 1 ] >= 0x30 && buffer[ idx + 1 ] <= 0x39 ) )
227+ {
228+ if let ( Some ( ch1) , Some ( ch2) ) =
229+ ( unhex_nibble ( buffer[ idx] ) , unhex_nibble ( buffer[ idx + 1 ] ) )
230+ {
231+ out_data. push ( ch1 << 4 | ch2) ;
232+ }
233+ idx += 2 ;
234+ } else {
235+ out_data. push ( 0x3d ) ;
236+ }
237+ } else if header && buffer[ idx] == 0x5f {
238+ out_data. push ( 0x20 ) ;
239+ idx += 1 ;
240+ } else {
241+ out_data. push ( buffer[ idx] ) ;
242+ idx += 1 ;
243+ }
244+ }
245+
246+ Ok ( out_data)
247+ } )
248+ }
249+
250+ #[ derive( FromArgs ) ]
251+ struct B2aQpArgs {
252+ #[ pyarg( any) ]
253+ data : ArgAsciiBuffer ,
254+ #[ pyarg( named, default = "false" ) ]
255+ quotetabs : bool ,
256+ #[ pyarg( named, default = "true" ) ]
257+ istext : bool ,
258+ #[ pyarg( named, default = "false" ) ]
259+ header : bool ,
260+ }
261+
262+ #[ pyfunction]
263+ fn b2a_qp ( args : B2aQpArgs ) -> PyResult < Vec < u8 > > {
264+ let s = args. data ;
265+ let quotetabs = args. quotetabs ;
266+ let istext = args. istext ;
267+ let header = args. header ;
268+ s. with_ref ( |buf| {
269+ let buflen = buf. len ( ) ;
270+ let mut linelen = 0 ;
271+ let mut odatalen = 0 ;
272+ let mut crlf = false ;
273+ let mut ch;
274+
275+ let mut inidx;
276+ let mut outidx;
277+
278+ inidx = 0 ;
279+ while inidx < buflen {
280+ if buf[ inidx] == 0x0a {
281+ break ;
282+ }
283+ inidx += 1 ;
284+ }
285+ if buflen > 0 && inidx < buflen && buf[ inidx - 1 ] == 0x0d {
286+ crlf = true ;
287+ }
288+
289+ inidx = 0 ;
290+ while inidx < buflen {
291+ let mut delta = 0 ;
292+ if ( buf[ inidx] > 126 )
293+ || ( buf[ inidx] == 0x3d )
294+ || ( header && buf[ inidx] == 0x5f )
295+ || ( buf[ inidx] == 0x2e
296+ && linelen == 0
297+ && ( inidx + 1 == buflen
298+ || buf[ inidx + 1 ] == 0x0a
299+ || buf[ inidx + 1 ] == 0x0d
300+ || buf[ inidx + 1 ] == 0 ) )
301+ || ( !istext && ( ( buf[ inidx] == 0x0d ) || ( buf[ inidx] == 0x0a ) ) )
302+ || ( ( buf[ inidx] == 0x09 || buf[ inidx] == 0x20 ) && ( inidx + 1 == buflen) )
303+ || ( ( buf[ inidx] < 33 )
304+ && ( buf[ inidx] != 0x0d )
305+ && ( buf[ inidx] != 0x0a )
306+ && ( quotetabs || ( ( buf[ inidx] != 0x09 ) && ( buf[ inidx] != 0x20 ) ) ) )
307+ {
308+ if ( linelen + 3 ) >= 76 {
309+ // MAXLINESIZE = 76
310+ linelen = 0 ;
311+ if crlf {
312+ delta += 3 ;
313+ } else {
314+ delta += 2 ;
315+ }
316+ }
317+ linelen += 3 ;
318+ delta += 3 ;
319+ inidx += 1 ;
320+ } else {
321+ if istext
322+ && ( ( buf[ inidx] == 0x0a )
323+ || ( ( inidx + 1 < buflen)
324+ && ( buf[ inidx] == 0x0d )
325+ && ( buf[ inidx + 1 ] == 0x0a ) ) )
326+ {
327+ linelen = 0 ;
328+ if ( inidx != 0 ) && ( ( buf[ inidx - 1 ] == 0x20 ) || ( buf[ inidx - 1 ] == 0x09 ) ) {
329+ delta += 2 ;
330+ }
331+ if crlf {
332+ delta += 2 ;
333+ } else {
334+ delta += 2 ;
335+ }
336+ if buf[ inidx] == 0x0d {
337+ inidx += 2 ;
338+ } else {
339+ inidx += 1 ;
340+ }
341+ } else {
342+ if ( inidx + 1 != buflen) && ( buf[ inidx + 1 ] != 0x0a ) && ( linelen + 1 ) >= 76
343+ {
344+ // MAXLINESIZE
345+ linelen = 0 ;
346+ if crlf {
347+ delta += 3 ;
348+ } else {
349+ delta += 2 ;
350+ }
351+ }
352+ linelen += 1 ;
353+ delta += 1 ;
354+ inidx += 1 ;
355+ }
356+ }
357+ odatalen += delta;
358+ }
359+
360+ let mut out_data = Vec :: < u8 > :: with_capacity ( odatalen) ;
361+ inidx = 0 ;
362+ outidx = 0 ;
363+ linelen = 0 ;
364+
365+ while inidx < buflen {
366+ if ( buf[ inidx] > 126 )
367+ || ( buf[ inidx] == 0x3d )
368+ || ( header && buf[ inidx] == 0x5f )
369+ || ( ( buf[ inidx] == 0x2e )
370+ && ( linelen == 0 )
371+ && ( inidx + 1 == buflen
372+ || buf[ inidx + 1 ] == 0x0a
373+ || buf[ inidx + 1 ] == 0x0d
374+ || buf[ inidx + 1 ] == 0 ) )
375+ || ( !istext && ( ( buf[ inidx] == 0x0d ) || ( buf[ inidx] == 0x0a ) ) )
376+ || ( ( buf[ inidx] == 0x09 || buf[ inidx] == 0x20 ) && ( inidx + 1 == buflen) )
377+ || ( ( buf[ inidx] < 33 )
378+ && ( buf[ inidx] != 0x0d )
379+ && ( buf[ inidx] != 0x0a )
380+ && ( quotetabs || ( ( buf[ inidx] != 0x09 ) && ( buf[ inidx] != 0x20 ) ) ) )
381+ {
382+ if ( linelen + 3 ) >= 76 {
383+ // MAXLINESIZE = 76
384+ out_data. push ( 0x3d ) ;
385+ outidx += 1 ;
386+ if crlf {
387+ out_data. push ( 0x0d ) ;
388+ outidx += 1 ;
389+ }
390+ out_data. push ( 0x0a ) ;
391+ outidx += 1 ;
392+ linelen = 0 ;
393+ }
394+ out_data. push ( 0x3d ) ;
395+ outidx += 1 ;
396+
397+ ch = hex_nibble ( buf[ inidx] >> 4 ) ;
398+ if ch >= 0x61 && ch <= 0x66 {
399+ ch -= 0x20 ;
400+ }
401+ out_data. push ( ch) ;
402+ ch = hex_nibble ( buf[ inidx] & 0xf ) ;
403+ if ch >= 0x61 && ch <= 0x66 {
404+ ch -= 0x20 ;
405+ }
406+ out_data. push ( ch) ;
407+
408+ outidx += 2 ;
409+ inidx += 1 ;
410+ linelen += 3 ;
411+ } else {
412+ if istext
413+ && ( ( buf[ inidx] == 0x0a )
414+ || ( ( inidx + 1 < buflen)
415+ && ( buf[ inidx] == 0x0d )
416+ && ( buf[ inidx + 1 ] == 0x0a ) ) )
417+ {
418+ linelen = 0 ;
419+ if ( outidx != 0 )
420+ && ( ( out_data[ outidx - 1 ] == 0x20 ) || ( out_data[ outidx - 1 ] == 0x09 ) )
421+ {
422+ ch = hex_nibble ( out_data[ outidx - 1 ] >> 4 ) ;
423+ if ch >= 0x61 && ch <= 0x66 {
424+ ch -= 0x20 ;
425+ }
426+ out_data. push ( ch) ;
427+ ch = hex_nibble ( out_data[ outidx - 1 ] & 0xf ) ;
428+ if ch >= 0x61 && ch <= 0x66 {
429+ ch -= 0x20 ;
430+ }
431+ out_data. push ( ch) ;
432+ out_data[ outidx - 1 ] = 0x3d ;
433+ outidx += 2 ;
434+ }
435+
436+ if crlf {
437+ out_data. push ( 0x0d ) ;
438+ outidx += 1 ;
439+ }
440+ out_data. push ( 0x0a ) ;
441+ outidx += 1 ;
442+ if buf[ inidx] == 0x0d {
443+ inidx += 2 ;
444+ } else {
445+ inidx += 1 ;
446+ }
447+ } else {
448+ if ( inidx + 1 != buflen) && ( buf[ inidx + 1 ] != 0x0a ) && ( linelen + 1 ) >= 76
449+ {
450+ // MAXLINESIZE = 76
451+ out_data. push ( 0x3d ) ;
452+ outidx += 1 ;
453+ if crlf {
454+ out_data. push ( 0x0d ) ;
455+ outidx += 1 ;
456+ }
457+ out_data. push ( 0x0a ) ;
458+ outidx += 1 ;
459+ linelen = 0 ;
460+ }
461+ linelen += 1 ;
462+ if header && buf[ inidx] == 0x20 {
463+ out_data. push ( 0x5f ) ;
464+ outidx += 1 ;
465+ inidx += 1 ;
466+ } else {
467+ out_data. push ( buf[ inidx] ) ;
468+ outidx += 1 ;
469+ inidx += 1 ;
470+ }
471+ }
472+ }
473+ }
474+ Ok ( out_data)
475+ } )
476+ }
184477
185478 #[ pyfunction]
186479 fn rlecode_hqx ( s : ArgAsciiBuffer ) -> PyResult < Vec < u8 > > {
0 commit comments