From 41c5d3b0cfa78fbdd0104af2faf1c6d885e7a487 Mon Sep 17 00:00:00 2001 From: Charlie Groves Date: Thu, 4 Aug 2022 13:35:52 -0400 Subject: [PATCH] Merge functions since there are no more options --- helix-view/src/base64/mod.rs | 102 +++++++++-------------------------- helix-view/src/clipboard.rs | 2 +- 2 files changed, 27 insertions(+), 77 deletions(-) diff --git a/helix-view/src/base64/mod.rs b/helix-view/src/base64/mod.rs index b5834dffc345e..137fdb218e0cd 100644 --- a/helix-view/src/base64/mod.rs +++ b/helix-view/src/base64/mod.rs @@ -1,86 +1,37 @@ use std::ops::{BitAnd, BitOr, Shl, Shr}; -pub fn encode>(input: T) -> String { - let encoded_size = - encoded_len(input.as_ref().len()).expect("integer overflow when calculating buffer size"); - let mut buf = vec![0; encoded_size]; - - encode_with_padding(input.as_ref(), &mut buf[..], encoded_size); - - String::from_utf8(buf).expect("Invalid UTF8") -} - -pub fn encoded_len(bytes_len: usize) -> Option { - let rem = bytes_len % 3; - - let complete_input_chunks = bytes_len / 3; - let complete_chunk_output = complete_input_chunks.checked_mul(4); - - if rem > 0 { - complete_chunk_output.and_then(|c| c.checked_add(4)) - } else { - complete_chunk_output - } -} - -fn encode_with_padding(input: &[u8], output: &mut [u8], expected_encoded_size: usize) { - debug_assert_eq!(expected_encoded_size, output.len()); - - let b64_bytes_written = encode_bytes(input, output); - - let padding_bytes = add_padding(input.len(), &mut output[b64_bytes_written..]); - - let encoded_bytes = b64_bytes_written - .checked_add(padding_bytes) - .expect("usize overflow when calculating b64 length"); - - debug_assert_eq!(expected_encoded_size, encoded_bytes); -} - -pub fn add_padding(input_len: usize, output: &mut [u8]) -> usize { - // TODO base on encoded len to use cheaper mod by 4 (aka & 7) - let rem = input_len % 3; - let mut bytes_written = 0; - for _ in 0..((3 - rem) % 3) { - output[bytes_written] = PAD_BYTE; - bytes_written += 1; - } - - bytes_written -} const PAD_BYTE: u8 = b'='; const ENCODE_TABLE: &[u8] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".as_bytes(); +const LOW_SIX_BITS: u32 = 0x3F; -fn encode_bytes(input: &[u8], output: &mut [u8]) -> usize { - // complete chunks first +pub fn encode(input: &[u8]) -> String { + let rem = input.len() % 3; + let remainder_output_chunk = if rem == 0 { 0 } else { 4 }; - const LOW_SIX_BITS: u32 = 0x3F; + let encoded_size = input.len() / 3 * 4 + remainder_output_chunk; - let rem = input.len() % 3; - // will never underflow + let mut output = vec![0; encoded_size]; + + // complete chunks first let complete_chunk_len = input.len() - rem; let mut input_index = 0_usize; let mut output_index = 0_usize; - if let Some(last_complete_chunk_index) = complete_chunk_len.checked_sub(3) { - while input_index <= last_complete_chunk_index { - let chunk = &input[input_index..input_index + 3]; - - // populate low 24 bits from 3 bytes - let chunk_int: u32 = - (chunk[0] as u32).shl(16) | (chunk[1] as u32).shl(8) | (chunk[2] as u32); - // encode 4x 6-bit output bytes - output[output_index] = ENCODE_TABLE[chunk_int.shr(18) as usize]; - output[output_index + 1] = - ENCODE_TABLE[chunk_int.shr(12_u8).bitand(LOW_SIX_BITS) as usize]; - output[output_index + 2] = - ENCODE_TABLE[chunk_int.shr(6_u8).bitand(LOW_SIX_BITS) as usize]; - output[output_index + 3] = ENCODE_TABLE[chunk_int.bitand(LOW_SIX_BITS) as usize]; - - input_index += 3; - output_index += 4; - } + while input_index < complete_chunk_len { + let chunk = &input[input_index..input_index + 3]; + + // populate low 24 bits from 3 bytes + let chunk_int: u32 = + (chunk[0] as u32).shl(16) | (chunk[1] as u32).shl(8) | (chunk[2] as u32); + // encode 4x 6-bit output bytes + output[output_index] = ENCODE_TABLE[chunk_int.shr(18) as usize]; + output[output_index + 1] = ENCODE_TABLE[chunk_int.shr(12_u8).bitand(LOW_SIX_BITS) as usize]; + output[output_index + 2] = ENCODE_TABLE[chunk_int.shr(6_u8).bitand(LOW_SIX_BITS) as usize]; + output[output_index + 3] = ENCODE_TABLE[chunk_int.bitand(LOW_SIX_BITS) as usize]; + + input_index += 3; + output_index += 4; } // then leftovers @@ -95,17 +46,16 @@ fn encode_bytes(input: &[u8], output: &mut [u8]) -> usize { // bottom 4 bits of [1], with the 2 bottom bits as zero output[output_index + 2] = ENCODE_TABLE[(chunk[1].shl(2_u8) as u32).bitand(LOW_SIX_BITS) as usize]; - - output_index += 3; + output[output_index + 3] = PAD_BYTE; } else if rem == 1 { let byte = input[input_index]; output[output_index] = ENCODE_TABLE[byte.shr(2) as usize]; output[output_index + 1] = ENCODE_TABLE[(byte.shl(4_u8) as u32).bitand(LOW_SIX_BITS) as usize]; - output_index += 2; + output[output_index + 2] = PAD_BYTE; + output[output_index + 3] = PAD_BYTE; } - - output_index + String::from_utf8(output).expect("Invalid UTF8") } #[cfg(test)] diff --git a/helix-view/src/clipboard.rs b/helix-view/src/clipboard.rs index 42860f8c9dc18..53e8862922424 100644 --- a/helix-view/src/clipboard.rs +++ b/helix-view/src/clipboard.rs @@ -159,7 +159,7 @@ mod provider { impl SetClipboardCommand { pub fn new(content: &str, clipboard_type: ClipboardType) -> Self { Self { - encoded_content: base64::encode(content), + encoded_content: base64::encode(content.as_bytes()), clipboard_type, } }