From 736738a2a798d58b1a73b0da146924a7e92ceba3 Mon Sep 17 00:00:00 2001 From: Jordi Polo Date: Sun, 26 Feb 2017 22:03:23 +0900 Subject: Adds File::with_name which automatically detects file format --- Cargo.toml | 1 + src/file/mod.rs | 51 ++++++++++++++++++++++++++++++++++++++------------- src/lib.rs | 3 +++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0f9fad1..2f38373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ yaml = ["yaml-rust"] [dependencies] nom = "^2.1" +lazy_static = "0.2" toml = { version = "0.2.1", optional = true } serde_json = { version = "0.9", optional = true } diff --git a/src/file/mod.rs b/src/file/mod.rs index 7f7c0fb..65253e8 100644 --- a/src/file/mod.rs +++ b/src/file/mod.rs @@ -2,7 +2,8 @@ use std::env; use std::error::Error; use std::io::{self, Read}; use std::fs; -use std::path::PathBuf; +use std::path::{PathBuf, Path}; +use std::collections::HashMap; use source::{Source, SourceBuilder}; @@ -17,7 +18,7 @@ mod json; #[cfg(feature = "yaml")] mod yaml; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Eq, PartialEq, Hash)] pub enum FileFormat { /// TOML (parsed with toml) #[cfg(feature = "toml")] @@ -32,18 +33,29 @@ pub enum FileFormat { Yaml, } -impl FileFormat { - fn extensions(&self) -> Vec<&'static str> { - match *self { - #[cfg(feature = "toml")] - FileFormat::Toml => vec!["toml"], - #[cfg(feature = "json")] - FileFormat::Json => vec!["json"], - #[cfg(feature = "yaml")] - FileFormat::Yaml => vec!["yaml", "yml"], - } +lazy_static! { + static ref ALL_EXTENSIONS: HashMap> = { + let mut formats: HashMap> = HashMap::new(); + + #[cfg(feature = "toml")] + formats.insert(FileFormat::Toml, vec!["toml"]); + + #[cfg(feature = "json")] + formats.insert(FileFormat::Json, vec!["json"]); + + #[cfg(feature = "yaml")] + formats.insert(FileFormat::Yaml, vec!["yaml", "yml"]); + formats + }; +} + + +impl FileFormat { + + fn extensions(&self) -> &'static Vec<&'static str> { + ALL_EXTENSIONS.get(self).unwrap() } #[allow(unused_variables)] @@ -107,7 +119,7 @@ impl FileSourceFile { loop { let mut filename = dir.as_path().join(basename.clone()); - for ext in &extensions { + for ext in extensions { filename.set_extension(ext); if filename.is_file() { @@ -172,6 +184,19 @@ impl File { } impl File { + // Given the basename of a file, tries reading it in all the registered formats. #21 + pub fn with_name(name: &str) -> File { + let possible_format = ALL_EXTENSIONS.iter().find( |&(_, extension_names)| + extension_names.iter().any( |&extension_name| + Path::new(&format!("{}.{}",name, extension_name)).exists() + ) + ); + match possible_format { + Some((format, _)) => File::new(name, *format), + None => panic!("The format of the file {} is not understood", name), + } + } + pub fn new(name: &str, format: FileFormat) -> File { File { format: format, diff --git a/src/lib.rs b/src/lib.rs index 15f9d49..bcfe2ee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,9 @@ extern crate serde_json; #[cfg(feature = "yaml")] extern crate yaml_rust; +#[macro_use] +extern crate lazy_static; + mod value; mod source; mod file; -- cgit v1.2.3