collada 0.17.0

A library for parsing COLLADA documents for mesh, skeletal and animation data
Documentation
use std::str::FromStr;
use xml::Element;
use xml::Xml::{CharacterNode, ElementNode};

pub fn parse_string_to_vector<T: FromStr>(string: &str) -> Vec<T> {
    string
        .trim()
        .replace("\r\n", "\n")
        .split(&[' ', '\n'][..])
        .map(|s| {
            let parse_result:Option<T> = s.parse().ok();
            match parse_result {
                Some(res) => return res,
                None => {
                    error!("unable to parse the folling line \n{s}");
                    panic!();
                }
            }
        }).collect()
}

pub fn get_array_content<T: FromStr>(element: &Element) -> Option<Vec<T>> {
    match element.children[0] {
        CharacterNode(ref contents) => Some(parse_string_to_vector(contents)),
        _ => None,
    }
}

pub fn has_attribute_with_value(e: &Element, name: &str, value: &str) -> bool {
    if let Some(s) = e.get_attribute(name, None) {
        s == value
    } else {
        false
    }
}

pub fn to_matrix_array(float_array: Vec<f32>) -> Vec<[[f32; 4]; 4]> {
    float_array
        .chunks(16)
        .map(|chunk| {
            let mut matrix = [[0f32; 4]; 4];
            for (&chunk_value, matrix_value) in chunk
                .iter()
                .zip(matrix.iter_mut().flat_map(|n| n.iter_mut()))
            {
                *matrix_value = chunk_value;
            }
            matrix
        })
        .collect()
}

///
/// Returns an iterator over all ElementNodes in an XML Element subtree with the given root,
/// using a pre-order tree traversal (root before children)
///
pub fn pre_order_iter<'a>(root: &'a Element) -> PreOrderIterator<'a> {
    PreOrderIterator { stack: vec![root] }
}

///
/// Returns an iterator over all ElementNodes in an XML Element subtree with the given root,
/// with their depth relative to the subtree root,
/// using a pre-order tree traversal (root before children)
///
pub fn pre_order_with_depth_iter<'a>(
    root: &'a Element
) -> PreOrderWithDepthIterator<'a> {
    PreOrderWithDepthIterator {
        stack: vec![(root, 0)],
    }
}

pub struct PreOrderIterator<'a> {
    stack: Vec<&'a Element>,
}

impl<'a> Iterator for PreOrderIterator<'a> {
    type Item = &'a Element;
    fn next(&mut self) -> Option<&'a Element> {
        let current_element = self.stack.pop();
        match current_element {
            Some(element) => {
                for child in element.children.iter().rev() {
                    if let ElementNode(ref e) = *child {
                        self.stack.push(e);
                    }
                }
            }
            None => (),
        }
        current_element
    }
}

pub struct PreOrderWithDepthIterator<'a> {
    stack: Vec<(&'a Element, usize)>,
}

impl<'a> Iterator for PreOrderWithDepthIterator<'a> {
    type Item = (&'a Element, usize);
    fn next(&mut self) -> Option<(&'a Element, usize)> {
        match self.stack.pop() {
            Some((element, depth)) => {
                for child in element.children.iter().rev() {
                    if let ElementNode(ref e) = *child {
                        self.stack.push((e, depth + 1));
                    }
                }
                Some((element, depth))
            }
            None => None,
        }
    }
}