| 805 | |
| 806 | #[pyfunction] |
| 807 | fn b2a_uu( |
| 808 | data: ArgBytesLike, |
| 809 | BacktickArg { backtick }: BacktickArg, |
| 810 | vm: &VirtualMachine, |
| 811 | ) -> PyResult<Vec<u8>> { |
| 812 | #[inline] |
| 813 | const fn uu_b2a(num: u8, backtick: bool) -> u8 { |
| 814 | if backtick && num == 0 { |
| 815 | 0x60 |
| 816 | } else { |
| 817 | b' ' + num |
| 818 | } |
| 819 | } |
| 820 | |
| 821 | data.with_ref(|b| { |
| 822 | let length = b.len(); |
| 823 | if length > 45 { |
| 824 | return Err(super::new_binascii_error( |
| 825 | "At most 45 bytes at once".to_owned(), |
| 826 | vm, |
| 827 | )); |
| 828 | } |
| 829 | let mut res = Vec::<u8>::with_capacity(2 + length.div_ceil(3) * 4); |
| 830 | res.push(uu_b2a(length as u8, backtick)); |
| 831 | |
| 832 | for chunk in b.chunks(3) { |
| 833 | let char_a = *chunk.first().unwrap(); |
| 834 | let char_b = *chunk.get(1).unwrap_or(&0); |
| 835 | let char_c = *chunk.get(2).unwrap_or(&0); |
| 836 | |
| 837 | res.push(uu_b2a(char_a >> 2, backtick)); |
| 838 | res.push(uu_b2a(((char_a & 0x3) << 4) | (char_b >> 4), backtick)); |
| 839 | res.push(uu_b2a(((char_b & 0xf) << 2) | (char_c >> 6), backtick)); |
| 840 | res.push(uu_b2a(char_c & 0x3f, backtick)); |
| 841 | } |
| 842 | |
| 843 | res.push(0xau8); |
| 844 | Ok(res) |
| 845 | }) |
| 846 | } |
| 847 | } |
| 848 | |
| 849 | struct Base64DecodeError(base64::DecodeError); |