|
@@ -3,134 +3,46 @@
|
|
|
// TASK: count all occurrences of <texture> tags in all xml files
|
|
|
// This will incrementally build the functionality so a lot is duplicated :)
|
|
|
|
|
|
-use std::ffi::OsStr;
|
|
|
-use std::fs::File;
|
|
|
-use std::io::BufReader;
|
|
|
+// use our xml module
|
|
|
+mod example_xml;
|
|
|
|
|
|
-use std::path::Path;
|
|
|
-use treexml;
|
|
|
-use walkdir::WalkDir; //an external lib for traversing dirs //easy path manipulations like os.path on python // an external crate for XML-related tasks like etree / elementtree
|
|
|
|
|
|
-// Every program starts with main()
|
|
|
-fn main() {
|
|
|
- let dir = "test"; // define our start dir here. Usually this would be a parameter passed to the program.
|
|
|
-
|
|
|
- // Let's look at how we can iterate a folder:
|
|
|
-
|
|
|
- // The dirty "python" way
|
|
|
- for f in WalkDir::new(&dir) {
|
|
|
- let file = f.unwrap();
|
|
|
- if file.path().is_file() {
|
|
|
- let ext = file.path().extension().unwrap();
|
|
|
- if ext == "xml" {
|
|
|
- dbg!(ext);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // The safe way without unwrap()s
|
|
|
- for file in WalkDir::new(&dir) {
|
|
|
- match file {
|
|
|
- Ok(valid_file) => {
|
|
|
- match valid_file.path().extension() {
|
|
|
- Some(ext) => {
|
|
|
- if ext == "xml" {
|
|
|
- dbg!(valid_file);
|
|
|
- // do something here
|
|
|
- }
|
|
|
- }
|
|
|
- None => (),
|
|
|
- }
|
|
|
- }
|
|
|
- Err(_e) => (),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // The functional way - produce a vec of valid files, then do something with it or pass it along
|
|
|
- let xml_files: Vec<_> = WalkDir::new(&dir)
|
|
|
- .into_iter() // creates an iterator
|
|
|
- .filter_map(|e| e.ok()) // filters out invalid entries
|
|
|
- .filter(|f| f.path().is_file()) // filters out directories
|
|
|
- .filter(|f| f.path().extension() == Some(OsStr::new("xml"))) // leaves xml - a bit verbose
|
|
|
- .collect();
|
|
|
|
|
|
- dbg!(&xml_files);
|
|
|
+// Functions "consume" vars
|
|
|
+fn say_hello(text: String) {
|
|
|
+ println!("hello {}", text);
|
|
|
+}
|
|
|
|
|
|
- for f in xml_files {
|
|
|
- dbg!(elements_from_xml(&f.path()));
|
|
|
- }
|
|
|
|
|
|
|
|
|
+// Last line returns
|
|
|
+fn mult(val1: f32, val2: f32) -> f32 {
|
|
|
+ val1 * val2
|
|
|
}
|
|
|
|
|
|
-pub fn elements_from_xml(direntry: &Path) -> u32 {
|
|
|
- let mut counter = 0;
|
|
|
- match File::open(direntry) {
|
|
|
- Ok(f) => {
|
|
|
- let buf_reader = BufReader::new(&f);
|
|
|
- match treexml::Document::parse(buf_reader) {
|
|
|
- Ok(doc) => match doc.root {
|
|
|
- Some(root) => {
|
|
|
- for child in root.children {
|
|
|
- if child.name == "texture" {
|
|
|
- counter += 1;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- None => (),
|
|
|
- },
|
|
|
- Err(_e) => (),
|
|
|
- }
|
|
|
- }
|
|
|
- Err(_e) => (),
|
|
|
- }
|
|
|
- counter
|
|
|
+fn mult_oldschool(val1: f32, val2: f32) -> f32 {
|
|
|
+ let result = val1 * val2;
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
-// The whole match thing is cool and all, but a bit long. Enter if let:
|
|
|
|
|
|
-fn let_test() {
|
|
|
- let value = Some("str"); // value is either Some(v) or None.
|
|
|
|
|
|
- // normal way:
|
|
|
- match value {
|
|
|
- Some(v) => {
|
|
|
- dbg!(v);
|
|
|
- }
|
|
|
- None => (),
|
|
|
- }
|
|
|
+// Every program starts with main()
|
|
|
+fn main() {
|
|
|
+
|
|
|
+ let name = String::from("Javier");
|
|
|
+ say_hello(name);
|
|
|
|
|
|
- // This is better:
|
|
|
- if let Some(v) = value {
|
|
|
- dbg!(v);
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
-// Now let us refactor the XML parser with if let:
|
|
|
-pub fn elements_from_xml_short(direntry: &Path) -> u32 {
|
|
|
- let mut counter = 0;
|
|
|
- if let Ok(f) = File::open(direntry) {
|
|
|
- let buf_reader = BufReader::new(&f);
|
|
|
- if let Ok(doc) = treexml::Document::parse(buf_reader) {
|
|
|
- if let Some(root) = doc.root {
|
|
|
- for child in root.children {
|
|
|
- if child.name == "texture" {
|
|
|
- counter += 1;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ let test = Some("dsd");
|
|
|
+ match test {
|
|
|
+ Some(value) => {
|
|
|
+ 1;
|
|
|
}
|
|
|
+ None => (),
|
|
|
}
|
|
|
- counter
|
|
|
-}
|
|
|
|
|
|
+ example_xml::xml();
|
|
|
|
|
|
-// A functional approach:
|
|
|
-pub fn elements_from_xml_functional(direntry: &Path) -> Option<usize> {
|
|
|
- File::open(direntry)
|
|
|
- .ok().map(|f| BufReader::new(f))
|
|
|
- .and_then(|f| treexml::Document::parse(f).ok() )
|
|
|
- .and_then(|r| r.root)
|
|
|
- .map(|r| r.children.into_iter().filter(|e| e.name == "texture").collect::<Vec<_>>().len())
|
|
|
|
|
|
-}
|
|
|
+}
|