Get the total length of the data decoded from this line reader.
(&self)
| 433 | |
| 434 | /// Get the total length of the data decoded from this line reader. |
| 435 | fn decoded_len<E: Encoding>(&self) -> Result<usize, Error> { |
| 436 | let mut buffer = [0u8; 4]; |
| 437 | let mut lines = self.clone(); |
| 438 | let mut line = match lines.next().transpose()? { |
| 439 | Some(l) => l, |
| 440 | None => return Ok(0), |
| 441 | }; |
| 442 | let mut base64_len = 0usize; |
| 443 | |
| 444 | loop { |
| 445 | base64_len = base64_len.checked_add(line.len()).ok_or(InvalidLength)?; |
| 446 | |
| 447 | match lines.next().transpose()? { |
| 448 | Some(l) => { |
| 449 | // Store the end of the line in the buffer so we can |
| 450 | // reassemble the last block to determine the real length |
| 451 | buffer.copy_from_slice(line.slice_tail(4)?); |
| 452 | |
| 453 | line = l |
| 454 | } |
| 455 | |
| 456 | // To compute an exact decoded length we need to decode the |
| 457 | // last Base64 block and get the decoded length. |
| 458 | // |
| 459 | // This is what the somewhat complex code below is doing. |
| 460 | None => { |
| 461 | // Compute number of bytes in the last block (may be unpadded) |
| 462 | let base64_last_block_len = match base64_len % 4 { |
| 463 | 0 => 4, |
| 464 | n => n, |
| 465 | }; |
| 466 | |
| 467 | // Compute decoded length without the last block |
| 468 | let decoded_len = encoding::decoded_len( |
| 469 | base64_len |
| 470 | .checked_sub(base64_last_block_len) |
| 471 | .ok_or(InvalidLength)?, |
| 472 | ); |
| 473 | |
| 474 | // Compute the decoded length of the last block |
| 475 | let mut out = [0u8; 3]; |
| 476 | let last_block_len = if line.len() < base64_last_block_len { |
| 477 | let buffered_part_len = base64_last_block_len |
| 478 | .checked_sub(line.len()) |
| 479 | .ok_or(InvalidLength)?; |
| 480 | |
| 481 | let offset = 4usize.checked_sub(buffered_part_len).ok_or(InvalidLength)?; |
| 482 | |
| 483 | for i in 0..buffered_part_len { |
| 484 | buffer[i] = buffer[offset.checked_add(i).ok_or(InvalidLength)?]; |
| 485 | } |
| 486 | |
| 487 | buffer[buffered_part_len..][..line.len()].copy_from_slice(line.remaining); |
| 488 | let buffer_len = buffered_part_len |
| 489 | .checked_add(line.len()) |
| 490 | .ok_or(InvalidLength)?; |
| 491 | |
| 492 | E::decode(&buffer[..buffer_len], &mut out)?.len() |
nothing calls this directly
no test coverage detected