(src: impl AsRef<[u8]>, dst: &mut [u8])
| 65 | |
| 66 | impl<T: Alphabet> Encoding for T { |
| 67 | fn decode(src: impl AsRef<[u8]>, dst: &mut [u8]) -> Result<&[u8], Error> { |
| 68 | let (src_unpadded, mut err) = if T::PADDED { |
| 69 | let (unpadded_len, e) = decode_padding(src.as_ref())?; |
| 70 | (&src.as_ref()[..unpadded_len], e) |
| 71 | } else { |
| 72 | (src.as_ref(), 0) |
| 73 | }; |
| 74 | |
| 75 | let dlen = decoded_len(src_unpadded.len()); |
| 76 | |
| 77 | if dlen > dst.len() { |
| 78 | return Err(Error::InvalidLength); |
| 79 | } |
| 80 | |
| 81 | let dst = &mut dst[..dlen]; |
| 82 | |
| 83 | let mut src_chunks = src_unpadded.chunks_exact(4); |
| 84 | let mut dst_chunks = dst.chunks_exact_mut(3); |
| 85 | for (s, d) in (&mut src_chunks).zip(&mut dst_chunks) { |
| 86 | err |= Self::decode_3bytes(s, d); |
| 87 | } |
| 88 | let src_rem = src_chunks.remainder(); |
| 89 | let dst_rem = dst_chunks.into_remainder(); |
| 90 | |
| 91 | err |= !(src_rem.is_empty() || src_rem.len() >= 2) as i16; |
| 92 | let mut tmp_out = [0u8; 3]; |
| 93 | let mut tmp_in = [b'A'; 4]; |
| 94 | tmp_in[..src_rem.len()].copy_from_slice(src_rem); |
| 95 | err |= Self::decode_3bytes(&tmp_in, &mut tmp_out); |
| 96 | dst_rem.copy_from_slice(&tmp_out[..dst_rem.len()]); |
| 97 | |
| 98 | if err == 0 { |
| 99 | validate_last_block::<T>(src.as_ref(), dst)?; |
| 100 | Ok(dst) |
| 101 | } else { |
| 102 | Err(Error::InvalidEncoding) |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | // TODO(tarcieri): explicitly checked/wrapped arithmetic |
| 107 | #[allow(clippy::integer_arithmetic)] |
nothing calls this directly
no test coverage detected