summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordi Polo <mumismo@gmail.com>2017-02-26 22:03:23 +0900
committerJordi Polo Carres <jcarres@mdsol.com>2017-02-26 22:06:04 +0900
commit736738a2a798d58b1a73b0da146924a7e92ceba3 (patch)
tree4af808782a27d812c19811bf8ae51f394db5bc68
parentc9ee1568fe212e4c352ec1afc52db44b34348fcd (diff)
Adds File::with_name which automatically detects file format
-rw-r--r--Cargo.toml1
-rw-r--r--src/file/mod.rs51
-rw-r--r--src/lib.rs3
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<FileFormat, Vec<&'static str>> = {
+ let mut formats: HashMap<FileFormat, Vec<_>> = 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<FileSourceString> {
}
impl File<FileSourceFile> {
+ // Given the basename of a file, tries reading it in all the registered formats. #21
+ pub fn with_name(name: &str) -> File<FileSourceFile> {
+ 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<FileSourceFile> {
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;