runtime_properties/
runtime-properties.rs

1/*!
2This example demonstrates how properties can be created and destroyed at runtime.
3*/
4
5#[derive(Debug, Default)]
6struct RuntimeProps {
7	// Store the list of runtime properties somewhere
8	props: Vec<Box<dyn cvar::IProperty>>,
9}
10
11impl RuntimeProps {
12	// Action to create new properties
13	fn create(&mut self, args: &str, writer: &mut dyn cvar::IWrite) {
14		// Crude argument parsing
15		let args = args.trim();
16		let first = args.split_ascii_whitespace().next().unwrap_or("");
17		let args = args[first.len()..].trim_start();
18		let second = args.split_ascii_whitespace().next().unwrap_or("");
19		let third = args[second.len()..].trim_start();
20		if first.len() == 0 {
21			let _ = writeln!(writer, "Invalid arguments! expecting <type> <name> <value>");
22			return;
23		}
24		match first {
25			"string" => {
26				let prop = cvar::OwnedProp(second.into(), String::from(third), String::from(third));
27				self.props.push(Box::new(prop));
28			},
29			"int" => {
30				let value: i32 = third.parse().unwrap();
31				let prop = cvar::OwnedProp(second.into(), value, value);
32				self.props.push(Box::new(prop));
33			},
34			"float" => {
35				let value: f32 = third.parse().unwrap();
36				let prop = cvar::OwnedProp(second.into(), value, value);
37				self.props.push(Box::new(prop));
38			},
39			_ => {
40				let _ = writeln!(writer, "Invalid type! supports string, int or float");
41			},
42		}
43	}
44	// Action to remove properties
45	fn destroy(&mut self, args: &str, writer: &mut dyn cvar::IWrite) {
46		if args.len() == 0 {
47			let _ = writeln!(writer, "Invalid arguments! expecting the name of the property to remove");
48			return;
49		}
50		self.props.retain(|prop| prop.name() != args);
51	}
52}
53
54impl cvar::IVisit for RuntimeProps {
55	fn visit(&mut self, f: &mut dyn FnMut(&mut dyn cvar::INode)) {
56		f(&mut cvar::Action("create!", |args, writer| self.create(args, writer)));
57		f(&mut cvar::Action("destroy!", |args, writer| self.destroy(args, writer)));
58		for prop in &mut self.props {
59			f(prop.as_inode());
60		}
61	}
62}
63
64fn main() {
65	let mut runtime_props = RuntimeProps::default();
66
67	// Create some runtime props
68	let mut writer = String::new();
69	cvar::console::invoke(&mut runtime_props, "create!", "float f 3.141592", &mut writer);
70	cvar::console::invoke(&mut runtime_props, "create!", "string s Hello World!", &mut writer);
71	cvar::console::invoke(&mut runtime_props, "create!", "int i 42", &mut writer);
72
73	// Inspect the underlying props
74	assert_eq!(runtime_props.props.len(), 3);
75	assert_eq!(runtime_props.props[0].get_value().to_string(), "3.141592");
76	assert_eq!(runtime_props.props[1].get_value().to_string(), "Hello World!");
77	assert_eq!(runtime_props.props[2].get_value().to_string(), "42");
78
79	println!("Hit enter to list all the cvars and their values.");
80	println!("Assign value to cvar with `<name> <value>`.");
81	println!("Create new cvars with `create! <type> <name> <value>`.");
82	println!("Destroy the cvars with `destroy! <name>.");
83
84	loop {
85		// Read input from stdin
86		let mut line = String::new();
87		if read_line(&mut line) {
88			break;
89		}
90
91		// Crude command line parsing
92		let (path, args) = split_line(&line);
93		cvar::console::poke(&mut runtime_props, path, args, &mut cvar::IoWriter::stdout());
94	}
95}
96
97// Reads a line from stdin and return true if there was a break
98pub fn read_line(line: &mut String) -> bool {
99	use std::io;
100	print!(">>> ");
101	let _ = io::Write::flush(&mut io::stdout());
102	return io::stdin().read_line(line).is_err() || line.is_empty();
103}
104
105pub fn split_line(line: &str) -> (&str, Option<&str>) {
106	let line = line.trim_start();
107	let path = line.split_ascii_whitespace().next().unwrap_or("");
108	let args = &line[path.len()..].trim();
109	(path, if args.len() == 0 { None } else { Some(args) })
110}