bsp_rs 0.1.0

A Valve BSP loader
Documentation
use std::collections::HashMap;

use com_goldsrc_formats::Vec3;

pub type Entity = HashMap<String, EntityValue>;

#[derive(Debug, PartialEq)]
pub enum EntityValue {
    String(String),
    Number(f32),
    Vec3(Vec3),
}

pub fn parse_entities(data: &str) -> Vec<Entity> {
    let mut map = Vec::new();

    for line in data.lines() {
        match line {
            "{" => map.push(Entity::default()),
            "}" => {}
            line => process_line(line, &mut map),
        }
    }

    map
}

fn process_line(line: &str, map: &mut Vec<Entity>) {
    let mut kv = line.split('"');
    if let Some(key) = kv.nth(1) {
        if let Some(value) = kv.nth(1) {
            if let Some(entity) = map.last_mut() {
                if let Ok(number) = value.parse::<f32>() {
                    entity.insert(key.to_string(), EntityValue::Number(number));
                    return;
                } else if let Some(vec3) = parse_vec3(value) {
                    entity.insert(key.to_string(), EntityValue::Vec3(vec3));
                    return;
                }
                entity.insert(key.to_string(), EntityValue::String(value.to_string()));
            }
        }
    }
}

fn parse_vec3(value: &str) -> Option<Vec3> {
    let components: Vec<&str> = value.split_whitespace().collect();

    if components.len() == 3 {
        if let (Ok(x), Ok(y), Ok(z)) = (
            components[0].parse(),
            components[1].parse(),
            components[2].parse(),
        ) {
            return Some(Vec3::new(x, y, z));
        }
    }

    None
}