I'm just starting learning Rust, and decided to knock up a fairly simple UDP listener. My first step is to load and parse a TOML config file (as this requires using external dependencies, involves IO and structs - all things handy to learn as I go along). I've got a working solution, but I'm eager to know if I've perhaps taken the long way round (it certainly seems so to me) and if I can improve the solution. I've added my current code below.
config/mod.rs:
pub mod loader;
pub mod file_loader;
#[derive(Debug)]
pub struct Config {
server: ServerConfig,
}
#[derive(Debug)]
pub struct ServerConfig {
port: i16,
max_packet_size: i64,
}
config/loader.rs:
use config::Config;
use std::{io, convert};
pub trait ConfigLoader {
fn load(&self) -> Result<Config, ConfigLoadError>;
}
#[derive(Debug)]
pub enum ConfigLoadError {
EmptyError,
LoadIoError(io::Error),
}
impl convert::From<io::Error> for ConfigLoadError {
fn from(err: io::Error) -> ConfigLoadError {
ConfigLoadError::LoadIoError(err)
}
}
config/file_loader.rs:
(or, where I think everything falls apart... everything up to now seems pretty simple and clean)
use std::fs::File;
use config::{Config,SyslogServerConfig};
use config::loader::{ConfigLoader,ConfigLoadError};
use std::io::Read;
extern crate toml;
#[derive(Debug)]
pub struct FileLoader {
pub file_path: &'static str,
}
impl ConfigLoader for FileLoader {
fn load(&self) -> Result<Config, ConfigLoadError> {
let mut config_file = try!(File::open(self.file_path));
let mut config_content = String::new();
try!(config_file.read_to_string(&mut config_content));
let value = toml::Parser::new(&config_content).parse().unwrap();
match value.get("server") {
Some(result) => {
let mut conf = Config{
syslog_server: ServerConfig{
port: 8080,
max_packet_size: 1024
}
};
match result.as_table() {
Some(server_table) => {
match server_table.get("port") {
Some(port) => conf.syslog_server.port = port.as_integer().unwrap() as i16,
None => conf.syslog_server.port = 8080,
};
match server_table.get("max_packet_size") {
Some(max_packet_size) => conf.syslog_server.max_packet_size = max_packet_size.as_integer().unwrap(),
None => conf.syslog_server.max_packet_size = 1024,
}
},
None => Err(ConfigLoadError::EmptyError),
};
Ok(conf)
},
None => Err(ConfigLoadError::EmptyError)
}
}
}
config.toml:
(The config file that is to be read and parsed)
[server]
port = 9000
max_packet_size = 1024
Testing this, everything works as expected, producing the below output. It seems like a fairly messy way around it though - especially the structure initialisation.
Ok(Config { server: ServerConfig { port: 9000, max_packet_size: 1024 } })
Any insight or pointers would be greatly appreciated!