lossy compression
This commit is contained in:
parent
242724d7fd
commit
8bfeb6d2f3
4 changed files with 194 additions and 37 deletions
|
@ -1,5 +1,56 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
pub fn cell_diff_4_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||||
|
const CELLS_X: usize = WIDTH / 4;
|
||||||
|
const CELLS_Y: usize = HEIGHT / 4;
|
||||||
|
|
||||||
|
let mut modified_cells = [[false; CELLS_Y]; CELLS_X];
|
||||||
|
|
||||||
|
let (mut cell_runs, modified_cells_flat) =
|
||||||
|
rle_255_decode(&unpack_nybbles(encoded), CELLS_X * CELLS_Y);
|
||||||
|
|
||||||
|
if cell_runs % 2 == 1 {
|
||||||
|
cell_runs += 1;
|
||||||
|
}
|
||||||
|
*reader += cell_runs / 2;
|
||||||
|
let encoded = &encoded[(cell_runs / 2)..];
|
||||||
|
|
||||||
|
let mut changed_cell_count = 0;
|
||||||
|
let mut i = 0;
|
||||||
|
for cellx in 0..CELLS_X {
|
||||||
|
for celly in 0..CELLS_Y {
|
||||||
|
let cell = modified_cells_flat[i] == 1;
|
||||||
|
modified_cells[cellx][celly] = cell;
|
||||||
|
if cell {
|
||||||
|
changed_cell_count += 1;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut frame = *prev_frame;
|
||||||
|
|
||||||
|
let changed_pixel_count = changed_cell_count * 4 * 4;
|
||||||
|
let (runs, new_pixels) = rle_255_decode(encoded, changed_pixel_count);
|
||||||
|
*reader += runs;
|
||||||
|
|
||||||
|
let mut index = 0;
|
||||||
|
|
||||||
|
for x in 0..WIDTH {
|
||||||
|
for y in 0..HEIGHT {
|
||||||
|
let cellx = x / 4;
|
||||||
|
let celly = y / 4;
|
||||||
|
let is_changed = modified_cells[cellx][celly];
|
||||||
|
if is_changed {
|
||||||
|
frame[x][y] = new_pixels[index];
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frame
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cell_diff_8_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
pub fn cell_diff_8_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||||
let bitmap = {
|
let bitmap = {
|
||||||
*reader += 3;
|
*reader += 3;
|
||||||
|
@ -11,7 +62,7 @@ pub fn cell_diff_8_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usi
|
||||||
|
|
||||||
let mut frame = *prev_frame;
|
let mut frame = *prev_frame;
|
||||||
let changed_pixel_count = bitmap.count_ones() as usize * 8 * 8;
|
let changed_pixel_count = bitmap.count_ones() as usize * 8 * 8;
|
||||||
let (runs, new_pixels) = rle_255_decode_until(encoded, changed_pixel_count);
|
let (runs, new_pixels) = rle_255_decode(encoded, changed_pixel_count);
|
||||||
*reader += runs;
|
*reader += runs;
|
||||||
|
|
||||||
let cells_x = WIDTH / 8;
|
let cells_x = WIDTH / 8;
|
||||||
|
@ -54,7 +105,7 @@ pub fn bg_strips_horizontal(_prev_frame: &Frame, encoded: &[u8], reader: &mut us
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rle_diff_horizontal(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
pub fn rle_diff_horizontal(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||||
let (runs, decoded) = rle_255_decode_until(encoded, FRAME_SIZE);
|
let (runs, decoded) = rle_255_decode(encoded, FRAME_SIZE);
|
||||||
*reader += runs;
|
*reader += runs;
|
||||||
let mut frame = *prev_frame;
|
let mut frame = *prev_frame;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -68,7 +119,7 @@ pub fn rle_diff_horizontal(prev_frame: &Frame, encoded: &[u8], reader: &mut usiz
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rle_diff_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
pub fn rle_diff_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||||
let (runs, decoded) = rle_255_decode_until(encoded, FRAME_SIZE);
|
let (runs, decoded) = rle_255_decode(encoded, FRAME_SIZE);
|
||||||
*reader += runs;
|
*reader += runs;
|
||||||
let mut frame = *prev_frame;
|
let mut frame = *prev_frame;
|
||||||
let mut dbg_frame = FRAME_0;
|
let mut dbg_frame = FRAME_0;
|
||||||
|
@ -86,7 +137,7 @@ pub fn rle_diff_vertical(prev_frame: &Frame, encoded: &[u8], reader: &mut usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rle_horizontal(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
pub fn rle_horizontal(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||||
let (runs, pixels) = rle_255_decode_until(encoded, FRAME_SIZE);
|
let (runs, pixels) = rle_255_decode(encoded, FRAME_SIZE);
|
||||||
*reader += runs;
|
*reader += runs;
|
||||||
let mut frame = FRAME_0;
|
let mut frame = FRAME_0;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -100,7 +151,7 @@ pub fn rle_horizontal(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rle_vertical(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
pub fn rle_vertical(_prev_frame: &Frame, encoded: &[u8], reader: &mut usize) -> Frame {
|
||||||
let (runs, pixels) = rle_255_decode_until(encoded, FRAME_SIZE);
|
let (runs, pixels) = rle_255_decode(encoded, FRAME_SIZE);
|
||||||
*reader += runs;
|
*reader += runs;
|
||||||
let mut frame = FRAME_0;
|
let mut frame = FRAME_0;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
|
@ -1,15 +1,66 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub fn cell_diff_8_vertical(prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
pub fn cell_diff_4_vertical(prev_frame: &Frame, frame: &Frame, loss: usize) -> EncodedFrame {
|
||||||
let cells_x = WIDTH / 8;
|
let loss = loss / 4;
|
||||||
let cells_y = HEIGHT / 8;
|
const CELLS_X: usize = WIDTH / 4;
|
||||||
let loss = 0;
|
const CELLS_Y: usize = HEIGHT / 4;
|
||||||
|
|
||||||
|
let mut modified_cells = [[0; CELLS_Y]; CELLS_X];
|
||||||
|
|
||||||
|
for cellx in 0..CELLS_X {
|
||||||
|
for celly in 0..CELLS_Y {
|
||||||
|
let mut changed = 0;
|
||||||
|
for dx in 0..4 {
|
||||||
|
for dy in 0..4 {
|
||||||
|
let x = cellx * 4 + dx;
|
||||||
|
let y = celly * 4 + dy;
|
||||||
|
let pixel = frame[x][y];
|
||||||
|
|
||||||
|
if pixel != prev_frame[x][y] {
|
||||||
|
changed += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if changed > loss {
|
||||||
|
modified_cells[cellx][celly] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut changed_pixels = Vec::new();
|
||||||
|
for x in 0..WIDTH {
|
||||||
|
for y in 0..HEIGHT {
|
||||||
|
let cellx = x / 4;
|
||||||
|
let celly = y / 4;
|
||||||
|
|
||||||
|
if modified_cells[cellx][celly] != 0 {
|
||||||
|
changed_pixels.push(frame[x][y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut modified_cells_flat = Vec::new();
|
||||||
|
for x in 0..CELLS_X {
|
||||||
|
for y in 0..CELLS_Y {
|
||||||
|
modified_cells_flat.push(modified_cells[x][y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut data = Vec::new();
|
||||||
|
data.extend_from_slice(&pack_nybbles(rle_encode(&modified_cells_flat, 15)));
|
||||||
|
data.extend_from_slice(&rle_255_encode(&changed_pixels));
|
||||||
|
|
||||||
|
EncodedFrame {
|
||||||
|
encoding: Encoding::CellDiff4VV,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cell_diff_8_vertical(prev_frame: &Frame, frame: &Frame, loss: usize) -> EncodedFrame {
|
||||||
|
const CELLS_X: usize = WIDTH / 8;
|
||||||
|
const CELLS_Y: usize = HEIGHT / 8;
|
||||||
|
|
||||||
let mut bitmap: u32 = 0;
|
let mut bitmap: u32 = 0;
|
||||||
let mut changed_pixels = Vec::new();
|
|
||||||
|
|
||||||
for cellx in 0..cells_x {
|
for cellx in 0..CELLS_X {
|
||||||
for celly in 0..cells_y {
|
for celly in 0..CELLS_Y {
|
||||||
let mut changed = 0;
|
let mut changed = 0;
|
||||||
for dx in 0..8 {
|
for dx in 0..8 {
|
||||||
for dy in 0..8 {
|
for dy in 0..8 {
|
||||||
|
@ -23,15 +74,16 @@ pub fn cell_diff_8_vertical(prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if changed > loss {
|
if changed > loss {
|
||||||
bitmap |= 1 << (cellx + cells_x * celly);
|
bitmap |= 1 << (cellx + CELLS_X * celly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut changed_pixels = Vec::new();
|
||||||
for x in 0..WIDTH {
|
for x in 0..WIDTH {
|
||||||
for y in 0..HEIGHT {
|
for y in 0..HEIGHT {
|
||||||
let cellx = x / 8;
|
let cellx = x / 8;
|
||||||
let celly = y / 8;
|
let celly = y / 8;
|
||||||
let bit = 1 << (cellx + cells_x * celly);
|
let bit = 1 << (cellx + CELLS_X * celly);
|
||||||
if (bitmap & bit) != 0 {
|
if (bitmap & bit) != 0 {
|
||||||
changed_pixels.push(frame[x][y]);
|
changed_pixels.push(frame[x][y]);
|
||||||
}
|
}
|
||||||
|
@ -150,14 +202,14 @@ pub fn rle_vertical(_prev_frame: &Frame, frame: &Frame) -> EncodedFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_white(_prev_frame: &Frame, _frame: &Frame) -> EncodedFrame {
|
pub fn fill_white(_prev_frame: &Frame, _frame: &Frame, _loss: usize) -> EncodedFrame {
|
||||||
EncodedFrame {
|
EncodedFrame {
|
||||||
encoding: Encoding::FillWhite,
|
encoding: Encoding::FillWhite,
|
||||||
data: Vec::new(),
|
data: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_black(_prev_frame: &Frame, _frame: &Frame) -> EncodedFrame {
|
pub fn fill_black(_prev_frame: &Frame, _frame: &Frame, _loss: usize) -> EncodedFrame {
|
||||||
EncodedFrame {
|
EncodedFrame {
|
||||||
encoding: Encoding::FillBlack,
|
encoding: Encoding::FillBlack,
|
||||||
data: Vec::new(),
|
data: Vec::new(),
|
||||||
|
|
|
@ -8,13 +8,13 @@ pub use util::*;
|
||||||
|
|
||||||
const INSPECT_ENC: bool = false;
|
const INSPECT_ENC: bool = false;
|
||||||
const INSPECT_DEC: bool = false;
|
const INSPECT_DEC: bool = false;
|
||||||
const MAX_ERROR: usize = 0;
|
const MAX_ERROR: usize = 4; // max wrong pixels
|
||||||
|
const MAX_LOSS: usize = 16; // highest "loss" value tried for all lossy encodings
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let frames = get_all_frames("../video/frames/");
|
let frames = get_all_frames("../video/frames/");
|
||||||
let encoded = encode(&frames);
|
let encoded = encode(&frames);
|
||||||
|
|
||||||
// todo print average bytes per frame for each encoding type
|
|
||||||
let mut stats: EnumMap<Encoding, u32> = EnumMap::default();
|
let mut stats: EnumMap<Encoding, u32> = EnumMap::default();
|
||||||
let mut reader = 0;
|
let mut reader = 0;
|
||||||
let mut last_frame = FRAME_0;
|
let mut last_frame = FRAME_0;
|
||||||
|
@ -49,34 +49,59 @@ fn main() {
|
||||||
|
|
||||||
fn encode(frames: &[Frame]) -> Vec<u8> {
|
fn encode(frames: &[Frame]) -> Vec<u8> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
let encodings: Vec<FrameEncoder> = vec![
|
let lossless_encodings: Vec<FrameEncoder> = vec![
|
||||||
enc::fill_white,
|
|
||||||
enc::fill_black,
|
|
||||||
enc::rle_horizontal,
|
enc::rle_horizontal,
|
||||||
enc::rle_vertical,
|
enc::rle_vertical,
|
||||||
enc::rle_diff_horizontal,
|
enc::rle_diff_horizontal,
|
||||||
enc::rle_diff_vertical,
|
enc::rle_diff_vertical,
|
||||||
enc::bg_strips_horizontal,
|
enc::bg_strips_horizontal,
|
||||||
|
];
|
||||||
|
let lossy_encodings: Vec<FrameEncoderLossy> = vec![
|
||||||
|
enc::fill_white,
|
||||||
|
enc::fill_black,
|
||||||
enc::cell_diff_8_vertical,
|
enc::cell_diff_8_vertical,
|
||||||
|
enc::cell_diff_4_vertical,
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut last_frame = FRAME_0;
|
let mut last_frame = FRAME_0;
|
||||||
for (i, frame) in frames.iter().enumerate() {
|
for (_i, frame) in frames.iter().enumerate() {
|
||||||
let mut options = Vec::new();
|
let mut options = Vec::new();
|
||||||
for encode in &encodings {
|
for encode in &lossless_encodings {
|
||||||
let encoded = encode(&last_frame, frame);
|
let encoded = encode(&last_frame, frame);
|
||||||
let decode = get_matching_decoder(encoded.encoding);
|
let decode = get_matching_decoder(encoded.encoding);
|
||||||
let decoded = decode(&last_frame, &encoded.data, &mut 0);
|
let decoded = decode(&last_frame, &encoded.data, &mut 0);
|
||||||
let error = frame_error(frame, &decoded);
|
let error = frame_error(frame, &decoded);
|
||||||
if error <= MAX_ERROR {
|
if error == 0 {
|
||||||
options.push(encoded);
|
options.push(encoded);
|
||||||
} else {
|
} else {
|
||||||
|
dbg!(&encoded);
|
||||||
|
println!("{:?}, error: {error}, frame: {_i}", encoded.encoding);
|
||||||
|
render_images(&frame, &decoded);
|
||||||
|
panic!("error in lossless compression");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for encode in &lossy_encodings {
|
||||||
|
for loss in 0..MAX_LOSS {
|
||||||
|
let encoded = encode(&last_frame, frame, loss);
|
||||||
|
let decode = get_matching_decoder(encoded.encoding);
|
||||||
|
let decoded = decode(&last_frame, &encoded.data, &mut 0);
|
||||||
|
let error = frame_error(frame, &decoded);
|
||||||
|
|
||||||
|
// if error > 0 && loss == 0 {
|
||||||
// dbg!(&encoded);
|
// dbg!(&encoded);
|
||||||
// println!("{:?}, error: {error}, frame: {i}", encoded.encoding);
|
// println!("{:?}, error: {error}, frame: {_i}", encoded.encoding);
|
||||||
// render_images(&frame, &decoded);
|
// render_images(&frame, &decoded);
|
||||||
// panic!("loss in compression");
|
// panic!("error in 'loss 0' compression");
|
||||||
|
// }
|
||||||
|
if error < MAX_ERROR {
|
||||||
|
options.push(encoded);
|
||||||
|
} else {
|
||||||
|
// higher loss value will mean more error so can be skipped
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
options.sort_by_key(|b| b.data.len());
|
options.sort_by_key(|b| b.data.len());
|
||||||
let best_encoding = options.into_iter().next().unwrap();
|
let best_encoding = options.into_iter().next().unwrap();
|
||||||
if INSPECT_ENC {
|
if INSPECT_ENC {
|
||||||
|
@ -99,10 +124,10 @@ fn encode(frames: &[Frame]) -> Vec<u8> {
|
||||||
#[derive(Debug, TryFromPrimitive, Enum, Copy, Clone)]
|
#[derive(Debug, TryFromPrimitive, Enum, Copy, Clone)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Encoding {
|
enum Encoding {
|
||||||
FillWhite,
|
FillBlack = 0,
|
||||||
FillBlack,
|
FillWhite = 1,
|
||||||
RLEHorizontal,
|
RLEHorizontal = 2,
|
||||||
RLEVertical,
|
RLEVertical = 3,
|
||||||
RLEDiffHorizontal,
|
RLEDiffHorizontal,
|
||||||
RLEDiffVertical,
|
RLEDiffVertical,
|
||||||
BGStripsH,
|
BGStripsH,
|
||||||
|
@ -114,7 +139,7 @@ enum Encoding {
|
||||||
// CellDiff4HH,
|
// CellDiff4HH,
|
||||||
// CellDiff4HV,
|
// CellDiff4HV,
|
||||||
// CellDiff4VH,
|
// CellDiff4VH,
|
||||||
// CellDiff4VV,
|
CellDiff4VV,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
|
fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
|
||||||
|
@ -134,11 +159,12 @@ fn get_matching_decoder(encoding: Encoding) -> FrameDecoder {
|
||||||
// Encoding::CellDiff4HH => todo!(),
|
// Encoding::CellDiff4HH => todo!(),
|
||||||
// Encoding::CellDiff4HV => todo!(),
|
// Encoding::CellDiff4HV => todo!(),
|
||||||
// Encoding::CellDiff4VH => todo!(),
|
// Encoding::CellDiff4VH => todo!(),
|
||||||
// Encoding::CellDiff4VV => todo!(),
|
Encoding::CellDiff4VV => dec::cell_diff_4_vertical,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type FrameEncoder = fn(previous_frame: &Frame, new_frame: &Frame) -> EncodedFrame;
|
type FrameEncoder = fn(previous_frame: &Frame, new_frame: &Frame) -> EncodedFrame;
|
||||||
|
type FrameEncoderLossy = fn(previous_frame: &Frame, new_frame: &Frame, loss: usize) -> EncodedFrame;
|
||||||
type FrameDecoder = fn(previous_frame: &Frame, encoded_bytes: &[u8], reader: &mut usize) -> Frame;
|
type FrameDecoder = fn(previous_frame: &Frame, encoded_bytes: &[u8], reader: &mut usize) -> Frame;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -107,13 +107,17 @@ pub fn render_images(left: &Frame, right: &Frame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rle_255_encode(raw: &[u8]) -> Vec<u8> {
|
pub fn rle_255_encode(raw: &[u8]) -> Vec<u8> {
|
||||||
|
rle_encode(raw, 255)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rle_encode(raw: &[u8], max: u8) -> Vec<u8> {
|
||||||
let mut encoded = Vec::new();
|
let mut encoded = Vec::new();
|
||||||
let mut last_val = 0;
|
let mut last_val = 0;
|
||||||
let mut run = 0;
|
let mut run = 0;
|
||||||
for &val in raw {
|
for &val in raw {
|
||||||
if val != last_val || run == 255 {
|
if val != last_val || run == max {
|
||||||
encoded.push(run);
|
encoded.push(run);
|
||||||
if run == 255 && val == last_val {
|
if run == max && val == last_val {
|
||||||
encoded.push(0);
|
encoded.push(0);
|
||||||
}
|
}
|
||||||
run = 1;
|
run = 1;
|
||||||
|
@ -126,7 +130,31 @@ pub fn rle_255_encode(raw: &[u8]) -> Vec<u8> {
|
||||||
encoded
|
encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rle_255_decode_until(encoded: &[u8], max_size: usize) -> (usize, Vec<u8>) {
|
pub fn pack_nybbles(mut nybbles: Vec<u8>) -> Vec<u8> {
|
||||||
|
if nybbles.len() % 2 == 1 {
|
||||||
|
nybbles.push(0);
|
||||||
|
}
|
||||||
|
assert!(nybbles.iter().all(|&n| n < 16));
|
||||||
|
let mut packed = Vec::with_capacity(nybbles.len() / 2);
|
||||||
|
for i in 0..(nybbles.len() / 2) {
|
||||||
|
let upper = nybbles[i * 2] << 4;
|
||||||
|
let lower = nybbles[i * 2 + 1] & 15;
|
||||||
|
let byte = upper | lower;
|
||||||
|
packed.push(byte);
|
||||||
|
}
|
||||||
|
packed
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unpack_nybbles(packed: &[u8]) -> Vec<u8> {
|
||||||
|
let mut nybbles = Vec::with_capacity(packed.len() * 2);
|
||||||
|
for &p in packed {
|
||||||
|
nybbles.push(p >> 4);
|
||||||
|
nybbles.push(p & 15);
|
||||||
|
}
|
||||||
|
nybbles
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rle_255_decode(encoded: &[u8], max_size: usize) -> (usize, Vec<u8>) {
|
||||||
let mut raw = Vec::new();
|
let mut raw = Vec::new();
|
||||||
let mut val = 0;
|
let mut val = 0;
|
||||||
let mut consumed_bytes = 0;
|
let mut consumed_bytes = 0;
|
||||||
|
|
Loading…
Reference in a new issue