use std::io::{Read, Write};
mod scanner;
use scanner::{
Scanner,
ScannerState,
ChrIndex, Message,
};
#[derive(Debug)]
pub struct KeyRemover {
scanner: Scanner,
buffer_size: usize,
first_buffer_index: usize,
buffer_queue: Vec<Vec<u8>>,
buffer_length_queue: Vec<usize>,
message_queue: Vec<Message>,
}
impl KeyRemover {
pub fn init(
buffer_size: usize,
keys_to_remove: Vec<String>,
) -> Self {
let scanner = Scanner::new(keys_to_remove);
Self {
scanner,
buffer_size,
first_buffer_index: 0,
buffer_queue: Vec::new(),
buffer_length_queue: Vec::new(),
message_queue: Vec::new(),
}
}
pub fn process<R, W>(&mut self, mut reader: R, mut writer: W) where
R: Read, W: Write,
{
let mut mode = Mode::Remain;
let mut first_buffer = vec![0; self.buffer_size];
let mut filled_byte_size = reader.read(&mut first_buffer).unwrap(); self.scanner.process_new_buffer(&first_buffer[..filled_byte_size]);
self.buffer_queue.push(first_buffer);
self.buffer_length_queue.push(filled_byte_size);
while filled_byte_size != 0 { self.message_queue.append(&mut self.scanner.queue);
let optional_data_index_to_write = match self.scanner.state {
ScannerState::WaitingNextKey => {
let last_buffer_index_to_write = self.scanner.next_buffer_index - 1;
let message_end_index = self.message_queue.len();
Some((last_buffer_index_to_write, message_end_index))
},
ScannerState::CheckingValueRange => {
if self.scanner.next_buffer_index == 1 {
None
} else {
let last_buffer_index_to_write = self.scanner.next_buffer_index - 2;
if last_buffer_index_to_write < self.first_buffer_index {
None
} else {
let message_end_index = self.get_message_end_index(last_buffer_index_to_write);
Some((last_buffer_index_to_write, message_end_index))
}
}
},
ScannerState::FindingNextComma => {
let cached_skip_end_msg = &self.scanner.skip_end_msg_cache;
let last_buffer_index_to_write = match self.get_optional_skip_end_index(cached_skip_end_msg) {
Some(chr_index) => chr_index.0 - 1,
None => panic!("Error 1"), };
if last_buffer_index_to_write < self.first_buffer_index {
None
} else {
let message_end_index = self.get_message_end_index(last_buffer_index_to_write);
Some((last_buffer_index_to_write, message_end_index))
}
},
_ => {
let chr_index = self.scanner.key_cand_opener_index();
if self.first_buffer_index < chr_index.0 {
let last_buffer_index_to_write = chr_index.0 - 1;
let message_end_index = self.get_message_end_index(last_buffer_index_to_write);
Some((last_buffer_index_to_write, message_end_index))
}else {
None
}
},
};
if let Some((last_buffer_index_to_write, message_end_index)) = optional_data_index_to_write {
let mut messages_to_write: Vec<Message> = self.message_queue.drain(0..message_end_index).collect();
if let Some(Message::SkipEndPreviousTo(chr_index)) = messages_to_write.first() {
if chr_index.1 == 0 && chr_index.0 == self.first_buffer_index {
messages_to_write.remove(0);
mode = Mode::Remain;
}
}
if let Mode::Skip = mode {
messages_to_write.insert(0, Message::SkipStartFrom((self.first_buffer_index, 0)));
}
if let Some(Message::SkipStartFrom(_)) = messages_to_write.last() {
messages_to_write.push(Message::SkipEndTo((
last_buffer_index_to_write,
self.buffer_length_queue[last_buffer_index_to_write-self.first_buffer_index]-1
)));
mode = Mode::Skip;
} else {
mode = Mode::Remain;
}
messages_to_write.chunks(2).rev().for_each(|messages| {
let skip_start_chr_index = match messages[0] {
Message::SkipStartFrom(chr_index) => {
(chr_index.0 - self.first_buffer_index, chr_index.1)
},
_ => panic!("Error 2"),
};
let skip_end_chr_index = match messages[1] {
Message::SkipEndTo(chr_index) => {
(chr_index.0 - self.first_buffer_index, chr_index.1)
},
Message::SkipEndPreviousTo(chr_index) => {
let chr_index = self.previous_chr_index(&chr_index);
(chr_index.0 - self.first_buffer_index, chr_index.1)
},
_ => panic!("Error 3"),
};
if skip_start_chr_index.0 < skip_end_chr_index.0 {
let buffer_index = skip_end_chr_index.0;
let buffer = &mut self.buffer_queue[buffer_index];
let buffer_length = &mut self.buffer_length_queue[buffer_index];
buffer.drain(..=skip_end_chr_index.1);
*buffer_length -= skip_end_chr_index.1 + 1;
for buffer_index in skip_start_chr_index.0+1..skip_end_chr_index.0 {
let buffer = &mut self.buffer_queue[buffer_index];
let buffer_length = &mut self.buffer_length_queue[buffer_index];
buffer.clear();
*buffer_length = 0;
}
let buffer_index = skip_start_chr_index.0;
let buffer = &mut self.buffer_queue[buffer_index];
let buffer_length = &mut self.buffer_length_queue[buffer_index];
buffer.drain(skip_start_chr_index.1..);
*buffer_length = skip_start_chr_index.1;
} else { let buffer_index = skip_start_chr_index.0;
let buffer = &mut self.buffer_queue[buffer_index];
let buffer_length = &mut self.buffer_length_queue[buffer_index];
buffer.drain(skip_start_chr_index.1..=skip_end_chr_index.1);
*buffer_length -= skip_end_chr_index.1 - skip_start_chr_index.1 + 1;
}
});
let count_of_buffer_to_write = last_buffer_index_to_write - self.first_buffer_index + 1;
for buffer_index in 0..count_of_buffer_to_write {
let buffer = &self.buffer_queue[buffer_index];
let length = self.buffer_length_queue[buffer_index];
writer.write_all(&buffer[..length]).unwrap();
};
self.buffer_queue.drain(..count_of_buffer_to_write);
self.buffer_length_queue.drain(..count_of_buffer_to_write);
self.first_buffer_index += count_of_buffer_to_write;
}
let mut next_buffer = vec![0; self.buffer_size];
filled_byte_size = reader.read(&mut next_buffer).unwrap(); self.buffer_length_queue.push(filled_byte_size);
self.scanner.process_new_buffer(&next_buffer[..filled_byte_size]);
self.buffer_queue.push(next_buffer);
}
writer.flush().unwrap();
}
fn get_message_end_index(&self, last_buffer_index_to_write: usize) -> usize {
let mut message_end_index = 0;
for message in self.message_queue.iter() {
let chr_index = match &message {
Message::SkipStartFrom(v) => v,
Message::SkipEndTo(v) => v,
Message::SkipEndPreviousTo(v) => v,
};
if chr_index.0 > last_buffer_index_to_write {
break
}
message_end_index += 1;
}
message_end_index
}
fn get_optional_skip_end_index(&self, message: &Message) -> Option<ChrIndex> {
match message {
Message::SkipStartFrom(_) => {
None
},
Message::SkipEndTo(chr_index) => {
Some(chr_index.clone())
},
Message::SkipEndPreviousTo(chr_index) => {
Some(self.previous_chr_index(chr_index))
},
}
}
fn previous_chr_index(&self, chr_index: &ChrIndex) -> ChrIndex {
if chr_index.1 == 0 {
let previous_buffer_index = chr_index.0 - 1;
let buffer_queue_index = previous_buffer_index - self.first_buffer_index;
(chr_index.0-1, self.buffer_length_queue[buffer_queue_index] - 1)
} else {
(chr_index.0, chr_index.1-1)
}
}
}
#[derive(Debug)]
enum Mode {
Remain,
Skip,
}
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use std::io::Cursor;
use super::*;
fn get_sample_json_string() -> String {
let str = "{
\"key_0\": {
\"key_0_0\": \"val_0_0\",
\"key_0_1\": \"val_0_1\",
\"key_0_2\": {
\"key_0_2_0\": [
{
\"key_0_2_0_0\": \"val_0_2_0_0\",
\"key_0_2_0_1\": \"val_0_2_0_1\"
},
{
\"key_0_2_1_0\": \"val_0_2_1_0\",
\"key_0_2_1_1\": \"val_0_2_1_1\"
},
{
\"key_0_2_2_0\": \"val_0_2_2_0\",
\"key_0_2_2_1\": \"val_0_2_2_1\"
}
]
}
}
}";
str.to_string()
}
fn print_sample_json() {
let sample_json_string = get_sample_json_string();
for (idx, string) in sample_json_string.as_bytes().iter().enumerate() {
println!("# {}: {}", idx, String::from_utf8([*string].to_vec()).unwrap());
}
}
#[test]
fn test_1() {
let sample_json_string = get_sample_json_string();
let cloned_input_string = sample_json_string.clone();
let mut key_remover = KeyRemover::init(128, vec!["key_0_2_0".to_string()]);
let input = Cursor::new(sample_json_string);
let mut output = Vec::new();
key_remover.process(input, &mut output);
println!("# Input");
println!("{:?}", cloned_input_string);
println!("# Output");
println!("{:?}", String::from_utf8(output).unwrap());
}
}