use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use byteorder::{BigEndian, ByteOrder};
extern crate hex_slice;
use hex_slice::AsHex;
use crate::data::color::ColorType;
use crate::data::layer::Layer;
use crate::data::property::Property;
use crate::data::property::PropertyPayload;
use crate::data::xcf::XcfCompression;
use crate::data::tiles::Tiles;
use crate::LayerColorValue;
use crate::PropertyIdentifier;
use crate::RgbaPixel;
pub struct XcfCreator {
pub version: u16,
pub data: Vec<u8>,
pub index: u64,
pub compression: XcfCompression,
}
impl XcfCreator {
fn extend_u32(&mut self, value: u32) {
let mut width_buf = vec![0; 4];
BigEndian::write_u32(&mut width_buf, value);
self.data.extend_from_slice(&width_buf);
self.index += 4;
}
fn extend_u64(&mut self, value: u64) {
let mut width_buf = vec![0; 8];
BigEndian::write_u64(&mut width_buf, value);
self.data.extend_from_slice(&width_buf);
self.index += 8;
}
fn buf_extend_u32(&mut self, data: &mut Vec<u8>, index: &mut u32, value: u32) {
let size = 4;
let mut width_buf = vec![0; size];
BigEndian::write_u32(&mut width_buf, value);
data.extend_from_slice(&width_buf);
*index += size as u32;
}
fn buf_extend_u64(&mut self, data: &mut Vec<u8>, index: &mut u32, value: u64) {
let size = 8;
let mut width_buf = vec![0; size];
BigEndian::write_u64(&mut width_buf, value);
data.extend_from_slice(&mut width_buf);
*index += size as u32;
}
fn create_signature(&mut self, gimp_version: u16) {
let mut signature = format!("gimp xcf v{:03}\0", gimp_version);
if gimp_version == 1 {
signature = "gimp xcf file\0".to_string();
}
self.data.extend_from_slice(signature.as_bytes());
self.index += 14;
}
fn v10_gimp_string(&mut self, data: &mut Vec<u8>, index: &mut u32, str: &[u8]) {
let str_count = str.len() as u32;
self.buf_extend_u32(data, index, str_count + 4);
data.extend_from_slice(str);
*index += str_count;
self.buf_extend_u32(data, index, 0);
}
fn gimp_string(&mut self, data: &mut Vec<u8>, index: &mut u32, str: &[u8]) {
let str_count = str.len() as u32 + 1;
self.buf_extend_u32(data, index, str_count);
data.extend_from_slice(str);
data.extend_from_slice(&[0]);
*index += str_count;
}
fn parasite_prop(&mut self, data: &mut Vec<u8>, index: &mut u32, parasite_title: &str, parasite_data: &str, flags: u32) {
let title_len = parasite_title.len() + 1;
self.buf_extend_u32(data, index, title_len as u32);
data.extend_from_slice(parasite_title.as_bytes());
data.extend_from_slice(&[0]);
*index += title_len as u32;
self.buf_extend_u32(data, index,flags);
let data_len = parasite_data.len() + 1;
self.buf_extend_u32(data, index,data_len as u32);
data.extend_from_slice(parasite_data.as_bytes());
data.extend_from_slice(&[0]);
*index += data_len as u32;
}
pub fn new(version: u16, width: u32, height: u32, color_type: ColorType) -> Self {
let data = vec![];
let index = 0;
let mut _self = XcfCreator {
version,
data,
index,
compression: XcfCompression::None,
};
_self.create_signature(version);
_self.extend_u32(width);
_self.extend_u32(height);
_self.extend_u32(color_type as u32);
if version >= 4 {
_self.extend_u32(150); }
_self
}
fn prop_end(&mut self, data: &mut Vec<u8>, index: &mut u32) {
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, 0);
}
pub fn add_properties(&mut self, properties: &Vec<Property>) {
let mut _has_compression = false;
for property in properties {
self.extend_u32(property.kind as u32);
match &property.payload {
PropertyPayload::Compression(_value) => {
self.extend_u32(property.length as u32);
self.data.extend_from_slice(&[_value.to_u8()]);
self.index += 1;
self.compression = _value.clone();
_has_compression = true;
}
PropertyPayload::ResolutionProperty(_value) => {
self.extend_u32(property.length as u32);
self.extend_u32(_value.xres.to_bits()); self.extend_u32(_value.yres.to_bits()); }
PropertyPayload::Tatoo(_value) | PropertyPayload::Unit(_value) => {
self.extend_u32(property.length as u32);
self.extend_u32(*_value);
}
PropertyPayload::Parasites(_parasites) => {
let mut parasite_prop_buf = vec![];
let mut parasite_prop_len = 0;
for parasite in _parasites {
self.parasite_prop(
&mut parasite_prop_buf,
&mut parasite_prop_len,
¶site.name,
¶site.data,
parasite.flags
);
}
self.extend_u32(parasite_prop_len); self.data.extend_from_slice(¶site_prop_buf);
self.index += parasite_prop_len as u64;
}
_ => {
self.extend_u32(property.length as u32); }
}
}
if self.version > 10 && !_has_compression {
self.extend_u32(PropertyIdentifier::PropCompression as u32);
self.extend_u32(1); self.data.extend_from_slice(&[XcfCompression::Rle as u8]);
self.index += 1;
self.compression = XcfCompression::Rle;
self.extend_u32(PropertyIdentifier::PropResolution as u32);
self.extend_u32(8); let value: f32 = 300.0;
self.extend_u32(value.to_bits()); self.extend_u32(value.to_bits());
self.extend_u32(PropertyIdentifier::PropTattoo as u32);
self.extend_u32(4); self.extend_u32(2);
self.extend_u32(PropertyIdentifier::PropUnit as u32);
self.extend_u32(4); self.extend_u32(1);
let mut parasite_prop_buf = vec![];
let mut parasite_prop_len = 0;
self.parasite_prop(
&mut parasite_prop_buf,
&mut parasite_prop_len,
"gimp-comment",
"Test Comment",
1
);
self.parasite_prop(
&mut parasite_prop_buf,
&mut parasite_prop_len,
"gimp-image-grid",
"(style solid)\n(fgcolor (color-rgba 0 0 0 1))\n(bgcolor (color-rgba 1 1 1 1))\n(xspacing 10)\n(yspacing 10)\n(spacing-unit inches)\n(xoffset 0)\n(yoffset 0)\n(offset-unit inches)\n",
1
);
self.extend_u32(PropertyIdentifier::PropParasites as u32);
self.extend_u32(parasite_prop_len); self.data.extend_from_slice(¶site_prop_buf);
self.index += parasite_prop_len as u64;
}
self.extend_u32(0);
self.extend_u32(0);
}
fn _add_layers_properties(&mut self, data: &mut Vec<u8>, index: &mut u32, layers_properties: &Vec<Property>) {
for layer_property in layers_properties {
self.buf_extend_u32(data, index, layer_property.kind as u32);
self.buf_extend_u32(data, index, layer_property.length as u32); match &layer_property.payload {
PropertyPayload::Compression(_value) => {
data.extend_from_slice(&[_value.to_u8()]);
*index += 1;
}
PropertyPayload::OpacityLayer(_value) => {
data
.extend_from_slice(&[_value.r(), _value.g(), _value.b(), _value.a()]);
*index += 4;
}
PropertyPayload::FloatOpacityLayer() => {
let float_slice = [63, 128, 0, 0];
data.extend_from_slice(&float_slice); *index += 4;
}
PropertyPayload::VisibleLayer() => {
let float_slice = [0, 0, 0, 1];
data.extend_from_slice(&float_slice); *index += 4;
}
PropertyPayload::OffsetsLayer(_offset_x, _offset_y) => {
self.buf_extend_u32(data, index, *_offset_x);
self.buf_extend_u32(data, index, *_offset_y);
}
PropertyPayload::LinkedLayer(_value)
| PropertyPayload::ColorTagLayer(_value)
| PropertyPayload::LockContentLayer(_value)
| PropertyPayload::LockAlphaLayer(_value)
| PropertyPayload::LockPositionLayer(_value)
| PropertyPayload::ApplyMaskLayer(_value)
| PropertyPayload::EditMaskLayer(_value)
| PropertyPayload::ShowMaskLayer(_value)
| PropertyPayload::ModeLayer(_value)
| PropertyPayload::BlendSpaceLayer(_value)
| PropertyPayload::CompositeSpaceLayer(_value)
| PropertyPayload::CompositeModeLayer(_value)
| PropertyPayload::Tatoo(_value) => {
self.buf_extend_u32(data, index, *_value);
}
_ => {}
}
}
if self.version > 10 && layers_properties.iter().len() == 0 {
self.buf_extend_u32(data, index, PropertyIdentifier::PropActiveLayer as u32);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropOpacity as u32);
self.buf_extend_u32(data, index, 4);
data.extend_from_slice(&[0, 0, 0, 255]);
*index += 4;
self.buf_extend_u32(data, index, PropertyIdentifier::PropFloatOpacity as u32);
self.buf_extend_u32(data, index, 4);
let float_slice = [63, 128, 0, 0];
data.extend_from_slice(&float_slice); *index += 4;
self.buf_extend_u32(data, index, PropertyIdentifier::PropVisible as u32);
self.buf_extend_u32(data, index, 4);
let float_slice = [0, 0, 0, 1];
data.extend_from_slice(&float_slice); *index += 4;
self.buf_extend_u32(data, index, PropertyIdentifier::PropLinked as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropColorTag as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropLockContent as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropLockAlpha as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropLockPosition as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropApplyMask as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropEditMask as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropShowMask as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropOffsets as u32);
self.buf_extend_u32(data, index, 8);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropMode as u32);
self.buf_extend_u32(data, index, 4); self.buf_extend_u32(data, index, 28);
self.buf_extend_u32(data, index, PropertyIdentifier::PropBlendSpace as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 0);
self.buf_extend_u32(data, index, PropertyIdentifier::PropCompositeSpace as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, u32::MAX);
self.buf_extend_u32(data, index, PropertyIdentifier::PropCompositeMode as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, u32::MAX);
self.buf_extend_u32(data, index, PropertyIdentifier::PropTattoo as u32);
self.buf_extend_u32(data, index, 4);
self.buf_extend_u32(data, index, 2);
}
self.prop_end(data, index);
}
fn _add_layers_v10(&mut self, _layers: &[Layer]) {
let mut intermediate_buf = vec![];
let mut layer_offset_zero_index = 0;
self.buf_extend_u32(&mut intermediate_buf, &mut layer_offset_zero_index, 0); self.buf_extend_u32(&mut intermediate_buf, &mut layer_offset_zero_index, 0);
self.index += layer_offset_zero_index as u64;
let mut layer_offset_one_buf = vec![];
let mut layer_offset_one_index = 0;
self.buf_extend_u32(
&mut layer_offset_one_buf,
&mut layer_offset_one_index,
self.index as u32 + 4,
);
layer_offset_one_buf.extend_from_slice(&intermediate_buf);
self.data.extend_from_slice(&layer_offset_one_buf);
self.index += layer_offset_one_index as u64;
self.extend_u32(1); self.extend_u32(1); self.extend_u32(0);
let mut layer_name_data = vec!();
let mut layer_name_len = 0;
self.v10_gimp_string(&mut layer_name_data, &mut layer_name_len, b"Background");
self.data.extend_from_slice(&layer_name_data);
self.index += layer_name_len as u64;
self.extend_u32(PropertyIdentifier::PropActiveLayer as u32); self.extend_u32(0);
self.extend_u32(PropertyIdentifier::PropOpacity as u32); self.extend_u32(4); self.extend_u32(RgbaPixel::new(0, 0, 0, 255).to_u32());
self.extend_u32(PropertyIdentifier::PropMode as u32); self.extend_u32(4); self.extend_u32(0);
self.extend_u32(PropertyIdentifier::PropFloatOpacity as u32); self.extend_u32(4); let float_slice = [63, 128, 0, 0];
self.data.extend_from_slice(&float_slice); self.index += 4;
self.extend_u32(PropertyIdentifier::PropVisible as u32); self.extend_u32(4); let float_slice = [0, 0, 0, 1];
self.data.extend_from_slice(&float_slice); self.index += 4;
self.extend_u32(PropertyIdentifier::PropLinked as u32); self.extend_u32(4); self.extend_u32(0);
self.extend_u32(0);
self.extend_u32(0);
self.extend_u32(self.index as u32 + 8);
self.extend_u32(0);
self.extend_u32(1); self.extend_u32(1); self.extend_u32(3);
self.extend_u32(self.index as u32 + 8);
self.extend_u32(0);
self.extend_u32(1); self.extend_u32(1); self.extend_u32(self.index as u32 + 8);
self.extend_u32(0);
let slice = [158, 36, 222];
self.data.extend_from_slice(&slice);
}
pub fn add_layers(&mut self, layers: &Vec<Layer>) {
if self.version < 11 {
self._add_layers_v10(layers);
return;
}
let nb_layers = layers.iter().len();
let mut layer_data = vec![];
let mut layer_index = 0;
for layer in layers {
layer_index += 1;
let mut layer_len = 0;
let tiles = Tiles::new(layer);
let layer_offset = self.index + (nb_layers - layer_index + 1) as u64 * 8 + layer_len as u64 + 16;
self.extend_u64(layer_offset);
self.buf_extend_u32(&mut layer_data, &mut layer_len, layer.width);
self.buf_extend_u32(&mut layer_data, &mut layer_len, layer.height);
self.buf_extend_u32(&mut layer_data, &mut layer_len, layer.kind.kind.clone() as u32);
self.gimp_string(&mut layer_data, &mut layer_len, layer.name.as_bytes());
self._add_layers_properties(&mut layer_data, &mut layer_len, &layer.properties);
let mut hierarchy_data = vec![];
let mut hierarchy_len = 0;
self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len,layer.pixels.width); self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len,layer.pixels.height);
let layer_has_alpha = LayerColorValue::has_alpha(layer.kind.kind.clone());
if layer_has_alpha {
self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len, 4); } else {
self.buf_extend_u32(&mut hierarchy_data, &mut hierarchy_len, 3); }
let mut tiles_headers = vec![];
let mut tiles_body = vec![];
let mut tiles_pixels: Vec<Vec<RgbaPixel>> = vec![];
for _x in 0..tiles.nb {
tiles_pixels.push(vec![]);
}
let mut pixel_index = 0;
let mut x = 0;
let mut y = 1;
for pixel in &layer.pixels.pixels {
pixel_index += 1;
x += 1;
let tile_x = (x as f32 / 64.0).ceil();
let tile_y = (y as f32 / 64.0).ceil();
tiles_pixels[tiles.nb_width as usize * (tile_y as usize - 1) + tile_x as usize - 1].push(*pixel);
if pixel_index % layer.width == 0 {
y += 1;
x = 0;
}
}
if self.compression == XcfCompression::Rle {
let nb_of_pixels = layer.pixels.pixels.iter().len() as u32;
let nb_pixels_of_layers = layer.pixels.width * layer.pixels.height;
if nb_pixels_of_layers != nb_of_pixels {
panic!(
"Number of pixels on the layers {} and pixels {} aren't equals",
nb_pixels_of_layers, nb_of_pixels
);
}
let mut offset_data = vec![];
let mut offset_len = 0;
let hierarchy_ofs = layer_offset + layer_len as u64 + 16;
self.buf_extend_u32(&mut offset_data, &mut offset_len,layer.pixels.width); self.buf_extend_u32(&mut offset_data, &mut offset_len,layer.pixels.height); self.buf_extend_u32(&mut offset_data, &mut offset_len,0);
let offset_index = hierarchy_ofs + offset_len as u64 + tiles.nb as u64 * 8 + 8;
for _tile in &tiles_pixels {
self.buf_extend_u64(&mut hierarchy_data, &mut hierarchy_len, offset_index); }
self.buf_extend_u64(&mut hierarchy_data, &mut hierarchy_len, 0);
let mut tiles_headers_len = 0;
for tile in &tiles_pixels {
let tile_index = offset_index as u32 + 16 + tiles.nb * 8 + tiles_body.len() as u32;
self.buf_extend_u32(&mut tiles_headers, &mut tiles_headers_len, tile_index);
self.buf_extend_u32(&mut tiles_headers, &mut tiles_headers_len, 0);
tiles_headers_len = 0;
let mut buffer_r = vec![];
let mut buffer_g = vec![];
let mut buffer_b = vec![];
let mut buffer_a = vec![];
for pixel in tile {
buffer_r.push(pixel.r());
buffer_g.push(pixel.g());
buffer_b.push(pixel.b());
if layer_has_alpha {
buffer_a.push(pixel.a());
}
}
let rle_r = rle_compress(&buffer_r);
tiles_body.extend(rle_r);
let rle_g = rle_compress(&buffer_g);
tiles_body.extend(rle_g);
let rle_b = rle_compress(&buffer_b);
tiles_body.extend(rle_b);
if layer_has_alpha {
let rle_a = rle_compress(&buffer_a);
tiles_body.extend(rle_a);
}
}
hierarchy_data.extend_from_slice(&offset_data);
hierarchy_len += offset_len;
self.buf_extend_u64(&mut layer_data, &mut layer_len, hierarchy_ofs); self.buf_extend_u64(&mut layer_data, &mut layer_len,0);
layer_data.extend_from_slice(&hierarchy_data);
layer_len += hierarchy_len;
tiles_headers.extend_from_slice(&[0, 0, 0, 0]);
layer_data.extend_from_slice(&tiles_headers);
layer_data.extend_from_slice(&tiles_body);
layer_len += tiles_headers.len() as u32 + tiles_body.len() as u32;
self.index += layer_len as u64;
} else {
panic!("not implemented");
}
}
self.extend_u64(0); self.extend_u64(0); self.data.extend_from_slice(&layer_data);
}
pub fn save(&mut self, path: &PathBuf) -> Result<File, crate::Error> {
let mut new_file = File::create(&path)?;
new_file.write_all(self.data.as_slice())?;
Ok(new_file)
}
}
pub fn short_run_identical(verbatim: &[u8]) -> Vec<u8> {
println!("short run identical");
if verbatim.len() < 1 {
panic!("Wrong verbatim lengh : {}", verbatim.len());
}
vec![(verbatim.len() - 1) as u8, verbatim[0]]
}
pub fn long_run_identical(verbatim: &[u8]) -> Vec<u8> {
println!("long run identical");
if verbatim.len() < 127 {
panic!("Wrong verbatim lengh : {}", verbatim.len());
}
let p = verbatim.len() / 256;
let q = verbatim.len() % 256;
vec![127, p as u8, q as u8, verbatim[0]]
}
pub fn run_identical(verbatim: &[u8]) -> Vec<u8> {
if verbatim.len() > 126 {
return long_run_identical(&verbatim);
}
short_run_identical(&verbatim)
}
pub fn short_run_diff(verbatim: &[u8]) -> Vec<u8> {
println!("short run diff");
if verbatim.len() < 1 {
panic!("Wrong verbatim lengh : {}", verbatim.len());
}
let mut r = vec![(256 - verbatim.len()) as u8];
r.extend_from_slice(verbatim);
r
}
pub fn long_run_diff(verbatim: &[u8]) -> Vec<u8> {
println!("long run diff");
if verbatim.len() < 127 {
panic!("Wrong verbatim lengh : {}", verbatim.len());
}
let p = verbatim.len() / 256;
let q = verbatim.len() % 256;
let mut r = vec![128, p as u8, q as u8];
r.extend_from_slice(verbatim);
r
}
pub fn run_diff(verbatim: &[u8]) -> Vec<u8> {
if verbatim.len() > 126 {
return long_run_diff(&verbatim);
}
short_run_diff(&verbatim)
}
pub fn is_identiqual(values: &[u8]) -> bool {
if values.len() < 2 {
panic!("Wrong values lengh : {}", values.len());
}
let value = values[0];
for v in &values[1..values.len()] {
if value != *v {
return false;
}
}
return true;
}
pub fn rle_compress(data: &Vec<u8>) -> Vec<u8> {
let mut compress_data = vec![];
let mut verbatim: Vec<u8> = vec![];
let mut i = 0;
for byte in data {
i += 1;
verbatim.push(*byte);
if i >= data.len() - 1 {
break;
}
let val = *byte;
let mut val_last_1 = val;
let mut val_last_2 = val;
if i > 1 {
val_last_1 = data[i - 2];
}
if i > 2 {
val_last_2 = data[i - 3];
}
let val_1 = data[i];
let val_2 = data[i + 1];
let mut val_3 = val_2;
if i < data.len() - 2 {
val_3 = data[i + 2];
}
if i == 2
&& val_last_1 == val
&& val != val_1 {
let buffer = short_run_identical(&verbatim);
compress_data.extend_from_slice(&buffer);
verbatim = vec![];
continue;
}
if i == 1
&& val != val_1
&& val_1 == val_2
&& val_2 == val_3 {
let buffer = run_diff(&verbatim);
compress_data.extend_from_slice(&buffer);
verbatim = vec![];
continue;
}
if i > 2
&& val_last_2 == val_last_1
&& val_last_1 == val
&& val != val_1 {
println!("f 2: {:?}", verbatim);
let buffer = run_identical(&verbatim);
compress_data.extend_from_slice(&buffer);
verbatim = vec![];
continue;
}
if i > 4 && i < data.len() - 2
&& is_identiqual(&vec![data[i - 3], data[i - 4], data[i - 5]])
&& val_last_1 == val
&& val != val_1
{
println!("f 3: {:?}", verbatim);
let buffer = run_identical(&verbatim);
compress_data.extend_from_slice(&buffer);
verbatim = vec![];
continue;
}
if i < data.len() - 2
&& val != val_1
&& val_1 == val_2
&& val_2 == val_3 {
println!("f 4");
let buffer = run_diff(&verbatim);
compress_data.extend_from_slice(&buffer);
verbatim = vec![];
continue;
}
}
verbatim.push(data[data.len() - 1]);
let val = verbatim[verbatim.len() - 1];
let mut val_last_1 = val;
let mut val_last_2 = val;
let mut val_last_3 = val;
if verbatim.len() > 1 {
val_last_1 = verbatim[verbatim.len() - 2];
}
if verbatim.len() > 2 {
val_last_2 = verbatim[verbatim.len() - 3];
}
if verbatim.len() > 3 {
val_last_3 = verbatim[verbatim.len() - 4];
}
let mut buffer;
if verbatim.len() >= 2 && val == val_last_1 && val_last_1 == val_last_2 {
println!("1.");
if data.len() == 1 {
buffer = vec![0, verbatim[0]];
} else {
buffer = run_identical(&verbatim);
}
} else if verbatim.len() >= 2 && val != val_last_1 && val_last_1 == val_last_2 && val_last_2 == val_last_3 {
println!("1.1");
buffer = run_identical(&verbatim[..verbatim.len() - 1]);
buffer.push(0);
buffer.push(val);
} else if verbatim.len() >= 2 && val == val_last_1 {
println!("2.");
buffer = run_diff(&verbatim[..verbatim.len() - 2]);
buffer.push(1);
buffer.push(verbatim[verbatim.len() - 1]);
} else {
println!("3.");
buffer = run_diff(&verbatim);
}
compress_data.extend_from_slice(&buffer);
compress_data
}