diff --git a/src/collection.rs b/src/collection.rs index e0598e8..7decdbc 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -1,12 +1,10 @@ -use std::io::prelude::*; use std::fs; -use std::fs::File; use std::path::Path; use std::path::PathBuf; use id3::Tag; use regex::Regex; -use toml; +use config::Config; use vfs::*; use error::*; @@ -37,12 +35,21 @@ pub struct SongTags { year: Option, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct User { name: String, password: String, } +impl User { + pub fn new(name: String, password: String) -> User { + User { + name: name, + password: password, + } + } +} + impl Album { fn read(collection: &Collection, real_path: &Path) -> Result { @@ -198,14 +205,6 @@ pub struct Collection { album_art_pattern: Regex, } -const CONFIG_MOUNT_DIRS: &'static str = "mount_dirs"; -const CONFIG_MOUNT_DIR_NAME: &'static str = "name"; -const CONFIG_MOUNT_DIR_SOURCE: &'static str = "source"; -const CONFIG_USERS: &'static str = "users"; -const CONFIG_USER_NAME: &'static str = "name"; -const CONFIG_USER_PASSWORD: &'static str = "password"; -const CONFIG_ALBUM_ART_PATTERN: &'static str = "album_art_pattern"; - impl Collection { pub fn new() -> Collection { Collection { @@ -215,126 +214,12 @@ impl Collection { } } - pub fn load_config(&mut self, config_path: &Path) -> Result<(), PError> { - // Open - let mut config_file = match File::open(config_path) { - Ok(c) => c, - Err(_) => return Err(PError::ConfigFileOpenError), - }; - - // Read - let mut config_file_content = String::new(); - match config_file.read_to_string(&mut config_file_content) { - Ok(_) => (), - Err(_) => return Err(PError::ConfigFileReadError), - }; - - // Parse - let parsed_config = toml::Parser::new(config_file_content.as_str()).parse(); - let parsed_config = match parsed_config { - Some(c) => c, - None => return Err(PError::ConfigFileParseError), - }; - - // Apply - try!(self.load_config_mount_points(&parsed_config)); - try!(self.load_config_users(&parsed_config)); - try!(self.load_config_album_art_pattern(&parsed_config)); - - Ok(()) - } - - fn load_config_album_art_pattern(&mut self, config: &toml::Table) -> Result<(), PError> { - let pattern = match config.get(CONFIG_ALBUM_ART_PATTERN) { - Some(s) => s, - None => return Ok(()), - }; - let pattern = match pattern { - &toml::Value::String(ref s) => s, - _ => return Err(PError::ConfigAlbumArtPatternParseError), - }; - self.album_art_pattern = match Regex::new(pattern) { - Ok(r) => r, - Err(_) => return Err(PError::ConfigAlbumArtPatternParseError), - }; - - Ok(()) - } - - fn load_config_users(&mut self, config: &toml::Table) -> Result<(), PError> { - let users = match config.get(CONFIG_USERS) { - Some(s) => s, - None => return Ok(()), - }; - - let users = match users { - &toml::Value::Array(ref a) => a, - _ => return Err(PError::ConfigUsersParseError), - }; - - for user in users { - let name = match user.lookup(CONFIG_USER_NAME) { - None => return Err(PError::ConfigUsersParseError), - Some(n) => n, - }; - let name = match name.as_str() { - None => return Err(PError::ConfigUsersParseError), - Some(n) => n, - }; - - let password = match user.lookup(CONFIG_USER_PASSWORD) { - None => return Err(PError::ConfigUsersParseError), - Some(n) => n, - }; - let password = match password.as_str() { - None => return Err(PError::ConfigUsersParseError), - Some(n) => n, - }; - - let user = User { - name: name.to_owned(), - password: password.to_owned(), - }; - self.users.push(user); + pub fn load_config(&mut self, config: &Config) -> Result<(), PError> { + self.album_art_pattern = config.album_art_pattern.clone(); + self.users = config.users.to_vec(); + for mount_dir in &config.mount_dirs { + try!(self.mount(mount_dir.name.as_str(), mount_dir.path.as_path())); } - - Ok(()) - } - - fn load_config_mount_points(&mut self, config: &toml::Table) -> Result<(), PError> { - let mount_dirs = match config.get(CONFIG_MOUNT_DIRS) { - Some(s) => s, - None => return Ok(()), - }; - - let mount_dirs = match mount_dirs { - &toml::Value::Array(ref a) => a, - _ => return Err(PError::ConfigMountDirsParseError), - }; - - for dir in mount_dirs { - let name = match dir.lookup(CONFIG_MOUNT_DIR_NAME) { - None => return Err(PError::ConfigMountDirsParseError), - Some(n) => n, - }; - let name = match name.as_str() { - None => return Err(PError::ConfigMountDirsParseError), - Some(n) => n, - }; - - let source = match dir.lookup(CONFIG_MOUNT_DIR_SOURCE) { - None => return Err(PError::ConfigMountDirsParseError), - Some(n) => n, - }; - let source = match source.as_str() { - None => return Err(PError::ConfigMountDirsParseError), - Some(n) => n, - }; - let source = PathBuf::from(source); - - try!(self.mount(name, source.as_path())); - } - Ok(()) } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..afb6e31 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,155 @@ +use regex; +use std::fs; +use std::io; +use std::io::Read; +use std::path; +use toml; + +use collection::User; +use vfs::MountDir; + +const CONFIG_MOUNT_DIRS: &'static str = "mount_dirs"; +const CONFIG_MOUNT_DIR_NAME: &'static str = "name"; +const CONFIG_MOUNT_DIR_SOURCE: &'static str = "source"; +const CONFIG_USERS: &'static str = "users"; +const CONFIG_USER_NAME: &'static str = "name"; +const CONFIG_USER_PASSWORD: &'static str = "password"; +const CONFIG_ALBUM_ART_PATTERN: &'static str = "album_art_pattern"; + +#[derive(Debug)] +pub enum ConfigError { + IoError(io::Error), + TOMLParseError, + RegexError(regex::Error), + AlbumArtPatternParseError, + UsersParseError, + MountDirsParseError, +} + +impl From for ConfigError { + fn from(err: io::Error) -> ConfigError { + ConfigError::IoError(err) + } +} + +impl From for ConfigError { + fn from(err: regex::Error) -> ConfigError { + ConfigError::RegexError(err) + } +} + +pub struct Config { + pub mount_dirs: Vec, + pub users: Vec, + pub album_art_pattern: regex::Regex, +} + +impl Config { + pub fn parse(config_path: &path::Path) -> Result { + let mut config_file = try!(fs::File::open(config_path)); + let mut config_file_content = String::new(); + try!(config_file.read_to_string(&mut config_file_content)); + let parsed_config = toml::Parser::new(config_file_content.as_str()).parse(); + let parsed_config = try!(parsed_config.ok_or(ConfigError::TOMLParseError)); + + let mut config = Config { + mount_dirs: Vec::new(), + users: Vec::new(), + album_art_pattern: regex::Regex::new("^Folder\\.png$").unwrap(), + }; + + try!(config.parse_mount_points(&parsed_config)); + try!(config.parse_users(&parsed_config)); + try!(config.parse_album_art_pattern(&parsed_config)); + + Ok(config) + } + + fn parse_album_art_pattern(&mut self, source: &toml::Table) -> Result<(), ConfigError> { + let pattern = match source.get(CONFIG_ALBUM_ART_PATTERN) { + Some(s) => s, + None => return Ok(()), + }; + let pattern = match pattern { + &toml::Value::String(ref s) => s, + _ => return Err(ConfigError::AlbumArtPatternParseError), + }; + self.album_art_pattern = try!(regex::Regex::new(pattern)); + Ok(()) + } + + fn parse_users(&mut self, source: &toml::Table) -> Result<(), ConfigError> { + let users = match source.get(CONFIG_USERS) { + Some(s) => s, + None => return Ok(()), + }; + + let users = match users { + &toml::Value::Array(ref a) => a, + _ => return Err(ConfigError::UsersParseError), + }; + + for user in users { + let name = match user.lookup(CONFIG_USER_NAME) { + None => return Err(ConfigError::UsersParseError), + Some(n) => n, + }; + let name = match name.as_str() { + None => return Err(ConfigError::UsersParseError), + Some(n) => n, + }; + + let password = match user.lookup(CONFIG_USER_PASSWORD) { + None => return Err(ConfigError::UsersParseError), + Some(n) => n, + }; + let password = match password.as_str() { + None => return Err(ConfigError::UsersParseError), + Some(n) => n, + }; + + let user = User::new(name.to_owned(), password.to_owned()); + self.users.push(user); + } + + Ok(()) + } + + fn parse_mount_points(&mut self, source: &toml::Table) -> Result<(), ConfigError> { + let mount_dirs = match source.get(CONFIG_MOUNT_DIRS) { + Some(s) => s, + None => return Ok(()), + }; + + let mount_dirs = match mount_dirs { + &toml::Value::Array(ref a) => a, + _ => return Err(ConfigError::MountDirsParseError), + }; + + for dir in mount_dirs { + let name = match dir.lookup(CONFIG_MOUNT_DIR_NAME) { + None => return Err(ConfigError::MountDirsParseError), + Some(n) => n, + }; + let name = match name.as_str() { + None => return Err(ConfigError::MountDirsParseError), + Some(n) => n, + }; + + let source = match dir.lookup(CONFIG_MOUNT_DIR_SOURCE) { + None => return Err(ConfigError::MountDirsParseError), + Some(n) => n, + }; + let source = match source.as_str() { + None => return Err(ConfigError::MountDirsParseError), + Some(n) => n, + }; + let source = path::PathBuf::from(source); + + let mount_dir = MountDir::new(name.to_owned(), source); + self.mount_dirs.push(mount_dir); + } + + Ok(()) + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6cb6e8d..c2f1c40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,10 @@ extern crate core; +extern crate id3; extern crate iron; extern crate mount; extern crate oven; extern crate params; extern crate regex; -extern crate id3; extern crate rustc_serialize; extern crate staticfile; extern crate toml; @@ -31,19 +31,23 @@ use staticfile::Static; mod api; mod collection; +mod config; mod error; mod ui; mod vfs; fn main() { + let config_file = Path::new("Polaris.toml"); + let config = config::Config::parse(&config_file).unwrap(); + println!("Starting up server"); let mut api_chain; { let api_handler; { let mut collection = collection::Collection::new(); - collection.load_config(Path::new("Polaris.toml")).unwrap(); + collection.load_config(&config).unwrap(); let collection = Arc::new(Mutex::new(collection)); api_handler = api::get_api_handler(collection); } @@ -58,7 +62,7 @@ fn main() { let mut mount = Mount::new(); mount.mount("/api/", api_chain); mount.mount("/", Static::new(Path::new("web"))); - let mut server = Iron::new(mount).http("localhost:3000").unwrap(); + let mut server = Iron::new(mount).http(("0.0.0.0", 5050)).unwrap(); ui::run(); diff --git a/src/vfs.rs b/src/vfs.rs index e3d69b1..2e69e45 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -4,6 +4,20 @@ use std::path::Path; use error::*; +pub struct MountDir { + pub name: String, + pub path: PathBuf, +} + +impl MountDir { + pub fn new(name: String, path: PathBuf) -> MountDir { + MountDir { + name: name, + path: path, + } + } +} + pub struct Vfs { mount_points: HashMap, }