vmf_forge/lib.rs
1//! A library for parsing and manipulating Valve Map Format (VMF) files.
2//!
3//! This library provides functionality to parse VMF files used in Source Engine games
4//! into Rust data structures, modify the data, and serialize it back into a VMF file.
5//!
6//! # Example
7//!
8//! ```
9//! use vmf_forge::prelude::*;
10//! use std::fs::File;
11//!
12//! fn main() -> Result<(), VmfError> {
13//! let mut file = File::open("vmf_examples/your_map.vmf")?;
14//! let vmf_file = VmfFile::parse_file(&mut file)?;
15//!
16//! println!("Map Version: {}", vmf_file.versioninfo.map_version);
17//!
18//! Ok(())
19//! }
20//! ```
21
22use indexmap::IndexMap;
23#[cfg(feature = "serialization")]
24use serde::{Deserialize, Serialize};
25
26pub mod parser;
27pub(crate) mod utils;
28pub mod vmf;
29
30pub mod errors;
31pub mod prelude;
32
33pub use errors::{VmfError, VmfResult};
34
35/// A trait for types that can be serialized into a VMF string representation.
36pub trait VmfSerializable {
37 /// Serializes the object into a VMF string.
38 ///
39 /// # Arguments
40 ///
41 /// * `indent_level` - The indentation level to use for formatting.
42 ///
43 /// # Returns
44 ///
45 /// A string representation of the object in VMF format.
46 fn to_vmf_string(&self, indent_level: usize) -> String;
47}
48
49pub mod vmf_file;
50pub use vmf_file::VmfFile;
51
52/// Represents a block in a VMF file, which can contain key-value pairs and other blocks.
53#[derive(Debug, Default)]
54pub struct VmfBlock {
55 /// The name of the block.
56 pub name: String,
57 /// The key-value pairs in the block.
58 pub key_values: IndexMap<String, String>, // what if Cow?!
59 /// The child blocks contained within this block.
60 pub blocks: Vec<VmfBlock>,
61}
62
63impl VmfBlock {
64 /// Serializes the `VmfBlock` into a string with the specified indentation level.
65 ///
66 /// # Arguments
67 ///
68 /// * `indent_level` - The indentation level to use for formatting.
69 ///
70 /// # Returns
71 ///
72 /// A string representation of the `VmfBlock` in VMF format.
73 pub fn serialize(&self, indent_level: usize) -> String {
74 let indent = "\t".repeat(indent_level);
75 let mut output = String::new();
76
77 // Opens the block with its name
78 output.push_str(&format!("{}{}\n", indent, self.name));
79 output.push_str(&format!("{}{{\n", indent));
80
81 // Adds all key-value pairs with the required indent
82 for (key, value) in &self.key_values {
83 output.push_str(&format!("{}\t\"{}\" \"{}\"\n", indent, key, value));
84 }
85
86 // Adds nested blocks with an increased indentation level
87 for block in &self.blocks {
88 output.push_str(&block.serialize(indent_level + 1));
89 }
90
91 // Closes the block
92 output.push_str(&format!("{}}}\n", indent));
93
94 output
95 }
96}