use crate::engine::*;
use std::fmt;
use serde::Serialize;
#[derive(Serialize)]
pub struct EncodeNode
{
pub name: String,
pub output: Vec<u8>,
pub decoders: Vec<DecodeNode>
}
#[derive(Serialize)]
pub struct DecodeNode
{
pub name: String,
pub output: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub encoders: Vec<EncodeNode>,
#[serde(skip)]
is_leaf: bool
}
#[derive(Serialize)]
pub struct DeencodeTree
{
pub input: String,
pub encoders: Vec<EncodeNode>
}
impl EncodeNode
{
pub fn make_nodes(input: &str, engines: &[&dyn Engine],
depth: usize)
-> Vec<EncodeNode>
{
let mut results = Vec::<EncodeNode>::new();
for &engine in engines.iter()
{
if let Some(output) = engine.encode(input)
{
let decoders =
DecodeNode::make_nodes(&output, engines, depth - 1);
results.push(EncodeNode {
name: engine.get_name(), output, decoders
});
};
}
results
}
pub fn deduplicate(&mut self, known_strings: &mut Vec<String>,
known_bytes: &mut Vec<Vec<u8>>)
{
let mut todelete: Vec<usize> = Vec::new();
known_bytes.push(self.output.clone());
for i in 0..self.decoders.len()
{
let decoder = &mut self.decoders[i];
if known_strings.contains(&decoder.output)
{
todelete.push(i);
continue;
}
decoder.deduplicate(known_strings, known_bytes);
if decoder.encoders.is_empty() && !decoder.is_leaf
{
todelete.push(i);
}
}
while let Some(i) = todelete.pop()
{
self.decoders.remove(i);
}
}
fn box_drawings(&self, prefix: &str, f: &mut fmt::Formatter<'_>)
-> fmt::Result
{
write!(f, "encoded as {} is", self.name)?;
for x in &self.output
{
write!(f, " {:02X}", x)?;
}
if 1 < self.decoders.len()
{
for i in 0..self.decoders.len() - 1
{
write!(f, "{}├╴", prefix)?;
let subprefix = String::from(prefix) + "│ ";
self.decoders[i].box_drawings(&subprefix, f)?;
}
}
if let Some(decoder) = self.decoders.last()
{
write!(f, "{}└╴", prefix)?;
let subprefix = String::from(prefix) + " ";
decoder.box_drawings(&subprefix, f)?;
}
Ok(())
}
}
impl DecodeNode
{
pub fn make_nodes(input: &[u8], engines: &[&dyn Engine],
depth: usize)
-> Vec<DecodeNode>
{
engines.iter()
.map(|e|
{
let output = e.decode(input);
let encoders = if 0 < depth
{
EncodeNode::make_nodes(&output, engines, depth)
}
else
{
Vec::new()
};
DecodeNode {
name: e.get_name(),
output,
encoders,
is_leaf: depth == 0
}
})
.collect()
}
pub fn deduplicate(&mut self, known_strings: &mut Vec<String>,
known_bytes: &mut Vec<Vec<u8>>)
{
let mut todelete: Vec<usize> = Vec::new();
known_strings.push(self.output.clone());
for i in 0..self.encoders.len()
{
let encoder = &mut self.encoders[i];
if known_bytes.contains(&encoder.output)
{
todelete.push(i);
continue;
}
encoder.deduplicate(known_strings, known_bytes);
if encoder.decoders.len() == 0
{
todelete.push(i);
}
}
while let Some(i) = todelete.pop()
{
self.encoders.remove(i);
}
}
fn box_drawings(&self, prefix: &str, f: &mut fmt::Formatter<'_>)
-> fmt::Result
{
write!(f, "decoded as {} is \"{}\"", self.name, self.output)?;
if 1 < self.encoders.len()
{
for i in 0..self.encoders.len() - 1
{
write!(f, "{}├╴", prefix)?;
let subprefix = String::from(prefix) + "│ ";
self.encoders[i].box_drawings(&subprefix, f)?;
}
}
if let Some(encoder) = self.encoders.last()
{
write!(f, "{}└╴", prefix)?;
let subprefix = String::from(prefix) + " ";
encoder.box_drawings(&subprefix, f)?;
}
Ok(())
}
}
impl DeencodeTree
{
pub fn deencode(input: &str, engines: &[&dyn Engine], depth: usize)
-> DeencodeTree
{
DeencodeTree {
input: input.to_owned(),
encoders: EncodeNode::make_nodes(input, engines, depth)
}
}
pub fn deduplicate(&mut self) -> (Vec<String>, Vec<Vec<u8>>)
{
let mut known_strings: Vec<String> = vec![self.input.clone()];
let mut known_bytes: Vec<Vec<u8>> = Vec::new();
let mut todelete: Vec<usize> = Vec::new();
for i in 0..self.encoders.len()
{
let encoder = &mut self.encoders[i];
if known_bytes.contains(&encoder.output)
{
todelete.push(i);
continue;
}
encoder.deduplicate(&mut known_strings, &mut known_bytes);
}
while let Some(i) = todelete.pop()
{
self.encoders.remove(i);
}
(known_strings, known_bytes)
}
pub fn box_drawings(&self, f: &mut fmt::Formatter<'_>)
-> fmt::Result
{
write!(f, "The string \"{}\"", self.input)?;
if 1 < self.encoders.len()
{
for i in 0..self.encoders.len() - 1
{
write!(f, "\n├╴")?;
self.encoders[i].box_drawings("\n│ ", f)?;
}
}
if let Some(encoder) = self.encoders.last()
{
write!(f, "\n└╴")?;
encoder.box_drawings("\n ", f)?;
}
Ok(())
}
}
impl fmt::Display for DeencodeTree
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
self.box_drawings(f)
}
}