Skip to content

Instantly share code, notes, and snippets.

@romanschejbal
Created July 2, 2020 13:08
Show Gist options
  • Save romanschejbal/fb9ccf352fe63ff4ac28531a735d5989 to your computer and use it in GitHub Desktop.
Save romanschejbal/fb9ccf352fe63ff4ac28531a735d5989 to your computer and use it in GitHub Desktop.
Tree thinning in Rust
extern crate xml;
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
use xml::reader::{EventReader, XmlEvent};
// debugging helper ignore this
fn indent(size: usize) -> String {
const INDENT: &'static str = " ";
(0..size)
.map(|_| INDENT)
.fold(String::with_capacity(size * INDENT.len()), |r, s| r + s)
}
struct Node {
name: String,
value: Option<String>,
depth: u32,
children: HashMap<String, Self>,
}
impl Node {
fn new(name: String, depth: u32) -> Self {
Self {
name,
value: None,
depth,
children: HashMap::new(),
}
}
fn find_or_create_child(&mut self, name: String, depth: u32) -> &mut Self {
if !self.children.contains_key(&name) {
let node = Self::new(name.clone(), depth);
self.children.insert(name.clone(), node);
}
self.children.get_mut(&name).unwrap()
}
}
impl std::fmt::Debug for Node {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let debug = writeln!(
f,
"{}- {} ({:?})",
indent(self.depth as usize),
self.name,
self.value
);
if let Err(e) = debug {
panic!(e);
}
self.children.iter().for_each(|(_, child)| {
child.fmt(f).unwrap();
});
debug
}
}
fn parse(parser: &mut EventReader<BufReader<File>>, parent: &mut Node, depth: u32) {
while let Ok(event) = parser.next() {
match event {
XmlEvent::StartDocument { .. } => {}
XmlEvent::StartElement { name, .. } => {
let child = parent.find_or_create_child(name.local_name, depth + 1);
parse(parser, child, depth + 1);
}
XmlEvent::Characters(characters) => {
parent.value = Some(characters);
}
XmlEvent::EndDocument { .. } | XmlEvent::EndElement { .. } => break,
_ => {}
}
}
}
fn main() {
let file = File::open("zbozi.xml").unwrap();
let file = BufReader::new(file);
let mut root = Node::new("ROOT".to_string(), 0);
let mut parser = EventReader::new(file);
let depth: u32 = 0;
parse(&mut parser, &mut root, depth);
println!("{:?}", root);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment