Created
November 15, 2023 02:36
-
-
Save wareya/538c356fbb82909f2dfebdd26f3a6ed7 to your computer and use it in GitHub Desktop.
rle compressor/decompressor that supports word lengths up to 4 bytes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn big_rle_compress(input : &[u8]) -> Vec<u8> | |
{ | |
let mut ret = Vec::new(); | |
let mut i = 0; | |
let mut mode = 0; // 0 - raw, 1 - rle | |
let mut mode_index = 0; | |
while i < input.len() | |
{ | |
let c = input[i]; | |
let mut j = i + 1; | |
while j < (i+64).min(input.len()) | |
{ | |
let b = input[j]; | |
if b != c | |
{ | |
break; | |
} | |
j += 1; | |
} | |
let mut n = j - i; | |
let mut rle_size = 1; | |
let mut j2 = i + 2; | |
while j2 + 1 < (i+128).min(input.len()) | |
{ | |
let c2 = input[i+1]; | |
let b = input[j2]; | |
let b2 = input[j2+1]; | |
if b2 != c2 || b != c | |
{ | |
break; | |
} | |
j2 += 2; | |
} | |
let n2 = (j2 - i) / 2; | |
if n2 * 2 > n | |
{ | |
rle_size = 2; | |
n = n2; | |
j = j2; | |
} | |
let mut j3 = i + 3; | |
while j3 + 2 < (i+192).min(input.len()) | |
{ | |
let c2 = input[i+1]; | |
let c3 = input[i+2]; | |
let b = input[j3]; | |
let b2 = input[j3+1]; | |
let b3 = input[j3+2]; | |
if b3 != c3 || b2 != c2 || b != c | |
{ | |
break; | |
} | |
j3 += 3; | |
} | |
let n3 = (j3 - i) / 3; | |
if n3 * 3 > n | |
{ | |
rle_size = 3; | |
n = n3; | |
j = j3; | |
} | |
let mut j4 = i + 4; | |
while j4 + 3 < (i+256).min(input.len()) | |
{ | |
let c2 = input[i+1]; | |
let c3 = input[i+2]; | |
let c4 = input[i+3]; | |
let b = input[j4]; | |
let b2 = input[j4+1]; | |
let b3 = input[j4+2]; | |
let b4 = input[j4+3]; | |
if b4 != c4 || b3 != c3 || b2 != c2 || b != c | |
{ | |
break; | |
} | |
j4 += 4; | |
} | |
let n4 = (j4 - i) / 4; | |
if n4 * 4 > n | |
{ | |
rle_size = 4; | |
n = n4; | |
j = j4; | |
} | |
if mode == 0 && (n > 2 || ret.len() == 0) | |
{ | |
mode = 1; | |
ret.push(0x00); | |
mode_index = ret.len() - 1; | |
} | |
else if mode == 1 && (n < 2 || ret.len() == 0) | |
{ | |
mode = 0; | |
ret.push(0x80); | |
mode_index = ret.len() - 1; | |
} | |
if mode == 0 | |
{ | |
let mut mode_n = ret[mode_index] & 0x7F; | |
if mode_n == 0x7F | |
{ | |
ret.push(0x80); | |
mode_index = ret.len() - 1; | |
mode_n = 0; | |
} | |
ret[mode_index] = 0x80 | (mode_n + 1); | |
ret.push(c); | |
i += 1; | |
} | |
else if mode == 1 | |
{ | |
let mut mode_n = ret[mode_index] & 0x7F; | |
if mode_n == 0x7F | |
{ | |
ret.push(0x00); | |
mode_index = ret.len() - 1; | |
mode_n = 0; | |
} | |
ret[mode_index] = mode_n + 1; | |
let mut n = (n - 1) as u8; | |
n |= (rle_size - 1) << 6; | |
ret.push(n); | |
ret.push(c); | |
if rle_size > 1 | |
{ | |
ret.push(input[i + 1]); | |
} | |
if rle_size > 2 | |
{ | |
ret.push(input[i + 2]); | |
} | |
if rle_size > 3 | |
{ | |
ret.push(input[i + 3]); | |
} | |
i = j; | |
} | |
} | |
ret | |
} | |
fn big_rle_decompress(input : &[u8]) -> Vec<u8> | |
{ | |
let mut ret = Vec::new(); | |
let mut i = 0; | |
while i < input.len() | |
{ | |
let m = input[i] as usize; | |
i += 1; | |
if m >= 0x80 | |
{ | |
for _ in 0..(m & 0x7F) | |
{ | |
let c = input[i]; | |
i += 1; | |
ret.push(c); | |
} | |
} | |
else | |
{ | |
for _ in 0..(m & 0x7F) | |
{ | |
let size = ((input[i] & 0xC0) >> 6) as usize + 1; | |
let n = (input[i] & 0x3F) as usize + 1; | |
i += 1; | |
if size == 1 | |
{ | |
let c = input[i]; | |
i += 1; | |
for _ in 0..n | |
{ | |
ret.push(c); | |
} | |
} | |
else if size == 2 | |
{ | |
let c = input[i]; | |
i += 1; | |
let c2 = input[i]; | |
i += 1; | |
for _ in 0..n | |
{ | |
ret.push(c); | |
ret.push(c2); | |
} | |
} | |
else if size == 3 | |
{ | |
let c = input[i]; | |
i += 1; | |
let c2 = input[i]; | |
i += 1; | |
let c3 = input[i]; | |
i += 1; | |
for _ in 0..n | |
{ | |
ret.push(c); | |
ret.push(c2); | |
ret.push(c3); | |
} | |
} | |
else if size == 4 | |
{ | |
let c = input[i]; | |
i += 1; | |
let c2 = input[i]; | |
i += 1; | |
let c3 = input[i]; | |
i += 1; | |
let c4 = input[i]; | |
i += 1; | |
for _ in 0..n | |
{ | |
ret.push(c); | |
ret.push(c2); | |
ret.push(c3); | |
ret.push(c4); | |
} | |
} | |
} | |
} | |
} | |
ret | |
} | |
fn rle_compress(input : &[u8]) -> Vec<u8> | |
{ | |
let mut ret = Vec::new(); | |
let mut i = 0; | |
let mut mode = 0; // 0 - raw, 1 - rle | |
let mut mode_index = 0; | |
while i < input.len() | |
{ | |
let c = input[i]; | |
let mut j = i + 1; | |
while j < (i+256).min(input.len()) | |
{ | |
let b = input[j]; | |
if b != c | |
{ | |
break; | |
} | |
j += 1; | |
} | |
let n = j - i; | |
if mode == 0 && (n > 2 || ret.len() == 0) | |
{ | |
mode = 1; | |
ret.push(0x00); | |
mode_index = ret.len() - 1; | |
} | |
else if mode == 1 && (n < 2 || ret.len() == 0) | |
{ | |
mode = 0; | |
ret.push(0x80); | |
mode_index = ret.len() - 1; | |
} | |
if mode == 0 | |
{ | |
let mut mode_n = ret[mode_index] & 0x7F; | |
if mode_n == 0x7F | |
{ | |
ret.push(0x80); | |
mode_index = ret.len() - 1; | |
mode_n = 0; | |
} | |
ret[mode_index] = 0x80 | (mode_n + 1); | |
ret.push(c); | |
i += 1; | |
} | |
else if mode == 1 | |
{ | |
let mut mode_n = ret[mode_index] & 0x7F; | |
if mode_n == 0x7F | |
{ | |
ret.push(0x00); | |
mode_index = ret.len() - 1; | |
mode_n = 0; | |
} | |
ret[mode_index] = mode_n + 1; | |
ret.push((n - 1) as u8); | |
ret.push(c); | |
i = j; | |
} | |
} | |
ret | |
} | |
fn rle_decompress(input : &[u8]) -> Vec<u8> | |
{ | |
let mut ret = Vec::new(); | |
let mut i = 0; | |
while i < input.len() | |
{ | |
let m = input[i] as usize; | |
i += 1; | |
if m >= 0x80 | |
{ | |
for _ in 0..(m & 0x7F) | |
{ | |
let c = input[i]; | |
i += 1; | |
ret.push(c); | |
} | |
} | |
else | |
{ | |
for _ in 0..(m & 0x7F) | |
{ | |
let n = input[i] as usize + 1; | |
i += 1; | |
let c = input[i]; | |
i += 1; | |
for _ in 0..n | |
{ | |
ret.push(c); | |
} | |
} | |
} | |
} | |
ret | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment