Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add decompress_from_utf16 function #13

Merged
merged 1 commit into from
Feb 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/compress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,13 @@ pub fn compress_str(input: &str) -> Vec<u32> {
compress(input, 16, |n| n)
}

/// Compress a [`&str`] as a valid [`String`].
///
#[inline]
pub fn compress_to_utf16(input: &str) -> String {
let buf = compress(input, 15, |n| n + 32);
buf.iter()
.map(|i| std::char::from_u32(*i).unwrap())
.map(|i| std::char::from_u32(*i).expect("`compress_to_utf16 output was not valid unicode`"))
.collect()
}

Expand Down
15 changes: 15 additions & 0 deletions src/decompress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ pub fn decompress_str(compressed: &[u32]) -> Option<String> {
decompress(&compressed, 16)
}

/// Decompress a [`&str`] compressed with [`crate::compress_to_utf16`].
///
/// # Errors
/// Returns an error if the compressed data could not be decompressed.
///
#[inline]
pub fn decompress_from_utf16(compressed: &str) -> Option<String> {
let compressed: Vec<u32> = compressed.chars().map(|c| u32::from(c) - 32).collect();
decompress(&compressed, 15)
}

#[inline]
pub fn decompress_uri(compressed: &[u32]) -> Option<String> {
// let compressed = compressed.replace(" ", "+"); //Is this even necessary?
Expand All @@ -72,8 +83,12 @@ pub fn decompress_uri(compressed: &[u32]) -> Option<String> {
decompress(&compressed?, 6)
}

/// The inner decompress function. All other decompress functions are built on top of this one.
/// It generally should not be used directly.
///
/// # Panics
/// Panics if `bits_per_char` is greater than the number of bits in a `u32`.
///
#[inline]
pub fn decompress(compressed: &[u32], bits_per_char: usize) -> Option<String> {
assert!(bits_per_char <= std::mem::size_of::<u32>() * 8);
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ pub use crate::{
},
decompress::{
decompress,
decompress_from_utf16,
decompress_str,
decompress_uri,
},
};

/// A utility function for converting a [`&str`] into a [`Vec`] of [`u32`]s,
/// where each [`u32`] is a valid [`char`].
///
pub fn str_to_u32_vec(buf: &str) -> Vec<u32> {
buf.chars().map(u32::from).collect()
}
52 changes: 34 additions & 18 deletions tests/common_legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,55 @@ use lz_str::{
compress_str,
compress_to_utf16,
compress_uri,
decompress_from_utf16,
decompress_str,
decompress_uri,
str_to_u32_vec,
};

const RED_STR: &str = "red";
const TEST_STR: &str = "The quick brown fox jumps over the lazy dog";
const TEST_STR_COMPRESSED: &[u32] = &[
2688, 45222, 64, 36362, 57494, 1584, 13700, 1120, 9987, 55325, 49270, 4108, 54016, 15392, 2758,
364, 112, 6594, 19459, 29469, 2049, 30466, 108, 1072, 3008, 10116, 38, 38915, 39168,
];

#[test]
pub fn round_red_uri() {
let compressed = compress_uri(&RED_STR);
assert_eq!(&compressed, &str_to_u32_vec("E4UwJkA"));
let decompressed = decompress_uri(&compressed).unwrap();
assert_eq!(RED_STR, decompressed);
pub fn round_test_uri() {
let compressed = compress_uri(&TEST_STR);
assert_eq!(
&compressed,
&str_to_u32_vec(
"CoCwpgBAjgrglgYwNYQEYCcD2B3AdhAM0wA8IArGAWwAcBnCTANzHQgBdwIAbAQwC8AnhAAmmAOZA"
)
);
let decompressed = decompress_uri(&compressed).expect("`round_test_uri` valid decompress");
assert_eq!(TEST_STR, decompressed);
}

#[test]
pub fn round_red() {
let compressed = compress_str(&RED_STR);
let compressed = compress_str(&TEST_STR);
let decompressed = decompress_str(&compressed).unwrap();
assert_eq!(RED_STR, decompressed);
assert_eq!(TEST_STR, decompressed);
}

#[test]
pub fn compress_red() {
let compressed = compress_str(&RED_STR);
assert_eq!(str_to_u32_vec("ᎅ〦䀀"), compressed);
pub fn compress_test() {
let compressed = compress_str(&TEST_STR);
assert_eq!(TEST_STR_COMPRESSED, compressed);
}

#[test]
pub fn compress_red_to_utf16() {
let compressed = compress_to_utf16(&RED_STR);
assert_eq!("\u{9e2}䰩䠠".to_string(), compressed);
pub fn compress_test_to_utf16() {
let compressed = compress_to_utf16(&TEST_STR);
assert_eq!("ՠⱉ䀨ऀ圤堸悋Ф〳䄖Ϙށ†䰠硠૦Ö<͘ⓠ᮸瑀̎Ƞ㘢ఢ砤硠Ŕ怮㈠", compressed);
}

#[test]
pub fn decompress_test_to_utf16() {
let decompressed = decompress_from_utf16("ՠⱉ䀨ऀ圤堸悋Ф〳䄖Ϙށ†䰠硠૦Ö<͘ⓠ᮸瑀̎Ƞ㘢ఢ砤硠Ŕ怮㈠ ")
.expect("Valid Decompress");
assert_eq!(TEST_STR, decompressed);
}

#[test]
Expand All @@ -44,8 +61,7 @@ pub fn compress_repeat() {
}

#[test]
pub fn decompress_red() {
let compressed = "ᎅ〦䀀".chars().map(u32::from).collect::<Vec<_>>();
let decompressed = decompress_str(&compressed).unwrap();
assert_eq!(RED_STR, decompressed);
pub fn decompress_test() {
let decompressed = decompress_str(TEST_STR_COMPRESSED).unwrap();
assert_eq!(TEST_STR, decompressed);
}