#[derive(Debug, Default)]
struct RuntimeProps {
props: Vec<Box<cvar::IProperty>>,
}
impl RuntimeProps {
fn create(&mut self, args: &[&str], console: &mut cvar::IConsole) {
if args.len() != 3 {
let _ = writeln!(console, "Invalid arguments! expecting <type> <name> <value>");
return;
}
match args[0] {
"string" => {
let prop = cvar::OwnedProp(args[1].into(), String::from(args[2]), String::from(args[2]));
self.props.push(Box::new(prop));
},
"int" => {
let value: i32 = args[2].parse().unwrap();
let prop = cvar::OwnedProp(args[1].into(), value, value);
self.props.push(Box::new(prop));
},
"float" => {
let value: f32 = args[2].parse().unwrap();
let prop = cvar::OwnedProp(args[1].into(), value, value);
self.props.push(Box::new(prop));
},
_ => {
let _ = writeln!(console, "Invalid type! supports string, int or float");
},
}
}
fn destroy(&mut self, args: &[&str], console: &mut cvar::IConsole) {
if args.len() != 1 {
let _ = writeln!(console, "Invalid arguments! expecting the name of the property to remove");
return;
}
self.props.retain(|prop| prop.name() != args[0]);
}
}
impl cvar::IVisit for RuntimeProps {
fn visit_mut(&mut self, f: &mut FnMut(&mut cvar::INode)) {
f(&mut cvar::Action("create!", "", |args, console| self.create(args, console)));
f(&mut cvar::Action("destroy!", "", |args, console| self.destroy(args, console)));
for prop in &mut self.props {
f(prop.as_inode_mut());
}
}
}
fn main() {
let mut runtime_props = RuntimeProps::default();
let mut output = String::new();
cvar::console::invoke(&mut runtime_props, "create!", &["float", "f", "3.141592"], &mut output);
cvar::console::invoke(&mut runtime_props, "create!", &["string", "s", "Hello World!"], &mut output);
cvar::console::invoke(&mut runtime_props, "create!", &["int", "i", "42"], &mut output);
assert_eq!(runtime_props.props.len(), 3);
assert_eq!(runtime_props.props[0].get(), "3.141592");
assert_eq!(runtime_props.props[1].get(), "Hello World!");
assert_eq!(runtime_props.props[2].get(), "42");
println!("Hit enter to list all the cvars and their values.");
println!("Assign value to cvar with `<name> <value>`.");
println!("Create new cvars with `create! <type> <name> <value>`.");
println!("Destroy the cvars with `destroy! <name>.");
loop {
let mut line = String::new();
if read_line(&mut line) {
break;
}
let args: Vec<&str> = line.split_whitespace().collect();
if args.is_empty() {
cvar::console::walk(&mut runtime_props, |path, node| {
match node.as_node_mut() {
cvar::NodeMut::Prop(prop) => {
println!("{} `{}`", path, prop.get());
},
cvar::NodeMut::List(_list) => (),
cvar::NodeMut::Action(_act) => {
println!("{}", path);
},
}
});
continue;
}
let path = args[0];
let args = &args[1..];
if !cvar::console::find(&mut runtime_props, path, |node| {
match node.as_node_mut() {
cvar::NodeMut::Prop(prop) => {
if args.len() > 0 {
if let Err(err) = prop.set(args[0]) {
println!("Cannot parse `{}`: {}.", args[0], err);
}
}
println!("{} `{}`", path, prop.get());
},
cvar::NodeMut::Action(act) => {
let mut console = cvar::IoConsole::stdout();
act.invoke(args, &mut console);
},
cvar::NodeMut::List(_) => {},
}
}) {
println!("Cannot find `{}`", path);
}
}
}
pub fn read_line(line: &mut String) -> bool {
use std::io;
print!(">>> ");
let _ = io::Write::flush(&mut io::stdout());
return io::stdin().read_line(line).is_err() || line.is_empty();
}