Skip to content

Commit 33110ae

Browse files
hachangmin6youknowone
authored andcommitted
add binascii a2b_qp
Signed-off-by: hachangmin6 <tom5757tom@pusan.ac.kr>
1 parent ba766e1 commit 33110ae

File tree

1 file changed

+293
-0
lines changed

1 file changed

+293
-0
lines changed

stdlib/src/binascii.rs

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)