#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};
use crate::nodes::node::Node;
pub trait BencodeVisitor {
type Error;
fn visit_integer(&mut self, value: i64) -> Result<(), Self::Error>;
fn visit_string(&mut self, value: &str) -> Result<(), Self::Error>;
fn visit_list_start(&mut self) -> Result<(), Self::Error>;
fn visit_list_end(&mut self) -> Result<(), Self::Error>;
fn visit_dict_start(&mut self) -> Result<(), Self::Error>;
fn visit_dict_key(&mut self, key: &str) -> Result<(), Self::Error>;
fn visit_dict_end(&mut self) -> Result<(), Self::Error>;
fn visit_none(&mut self) -> Result<(), Self::Error>;
}
pub trait BencodeVisitable {
fn accept<V: BencodeVisitor>(&self, visitor: &mut V) -> Result<(), V::Error>;
}
impl BencodeVisitable for Node {
fn accept<V: BencodeVisitor>(&self, visitor: &mut V) -> Result<(), V::Error> {
match self {
Node::Integer(val) => visitor.visit_integer(*val),
Node::Str(val) => visitor.visit_string(val),
Node::List(items) => {
visitor.visit_list_start()?;
for item in items {
item.accept(visitor)?;
}
visitor.visit_list_end()
}
Node::Dictionary(items) => {
visitor.visit_dict_start()?;
if items.len() <= 16 {
let mut stack: [Option<(&String, &Node)>; 16] = [None; 16];
let mut count = 0;
for pair in items {
stack[count] = Some((pair.0, pair.1));
count += 1;
}
let slice = &mut stack[..count];
slice.sort_unstable_by(|a, b| a.unwrap().0.cmp(b.unwrap().0));
for item in slice.iter() {
let (key, value) = item.unwrap();
visitor.visit_dict_key(key)?;
value.accept(visitor)?;
}
} else {
let mut sorted: Vec<_> = items.iter().collect();
sorted.sort_unstable_by(|a, b| a.0.cmp(b.0));
for (key, value) in sorted {
visitor.visit_dict_key(key)?;
value.accept(visitor)?;
}
}
visitor.visit_dict_end()
}
Node::None => visitor.visit_none(),
}
}
}