From 2dc6a74b84825f65142c1fa7d3e67cd4f35ee3cb Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Wed, 8 Mar 2017 11:09:37 -0800 Subject: Initial work on deep serde integration --- src/file/mod.rs | 219 -------------------------------------------------------- 1 file changed, 219 deletions(-) delete mode 100644 src/file/mod.rs (limited to 'src/file/mod.rs') diff --git a/src/file/mod.rs b/src/file/mod.rs deleted file mode 100644 index 7f7c0fb..0000000 --- a/src/file/mod.rs +++ /dev/null @@ -1,219 +0,0 @@ -use std::env; -use std::error::Error; -use std::io::{self, Read}; -use std::fs; -use std::path::PathBuf; - -use source::{Source, SourceBuilder}; - -mod nil; - -#[cfg(feature = "toml")] -mod toml; - -#[cfg(feature = "json")] -mod json; - -#[cfg(feature = "yaml")] -mod yaml; - -#[derive(Clone, Copy)] -pub enum FileFormat { - /// TOML (parsed with toml) - #[cfg(feature = "toml")] - Toml, - - /// JSON (parsed with serde_json) - #[cfg(feature = "json")] - Json, - - /// YAML (parsed with yaml_rust) - #[cfg(feature = "yaml")] - 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"], - } - } - - #[allow(unused_variables)] - fn parse(&self, text: &str, namespace: Option<&String>) -> Result, Box> { - match *self { - #[cfg(feature = "toml")] - FileFormat::Toml => toml::Content::parse(text, namespace), - - #[cfg(feature = "json")] - FileFormat::Json => json::Content::parse(text, namespace), - - #[cfg(feature = "yaml")] - FileFormat::Yaml => yaml::Content::parse(text, namespace), - } - } -} - -pub trait FileSource { - fn try_build(&self, - format: FileFormat, - namespace: Option<&String>) - -> Result, Box>; -} - -pub struct FileSourceString(String); - -impl FileSource for FileSourceString { - fn try_build(&self, - format: FileFormat, - namespace: Option<&String>) - -> Result, Box> { - format.parse(&self.0, namespace) - } -} - -pub struct FileSourceFile { - /// Basename of configuration file - name: String, - - /// Directory where configuration file is found - /// When not specified, the current working directory (CWD) is considered - path: Option, -} - -impl FileSourceFile { - // Find configuration file - // Use algorithm similar to .git detection by git - fn find_file(&self, format: FileFormat) -> Result> { - // Build expected configuration file - let mut basename = PathBuf::new(); - let extensions = format.extensions(); - - if let Some(ref path) = self.path { - basename.push(path.clone()); - } - - basename.push(self.name.clone()); - - // Find configuration file (algorithm similar to .git detection by git) - let mut dir = env::current_dir()?; - - loop { - let mut filename = dir.as_path().join(basename.clone()); - for ext in &extensions { - filename.set_extension(ext); - - if filename.is_file() { - // File exists and is a file - return Ok(filename); - } - } - - // Not found.. travse up via the dir - if !dir.pop() { - // Failed to find the configuration file - return Err(io::Error::new(io::ErrorKind::NotFound, - format!("configuration file \"{}\" not found", - basename.to_string_lossy())) - .into()); - } - } - } -} - -impl FileSource for FileSourceFile { - fn try_build(&self, - format: FileFormat, - namespace: Option<&String>) - -> Result, Box> { - // Find file - let filename = self.find_file(format)?; - - // Read contents from file - let mut file = fs::File::open(filename)?; - let mut text = String::new(); - file.read_to_string(&mut text)?; - - // Parse the file - format.parse(&text, namespace) - } -} - -pub struct File { - /// Source of the file - source: T, - - /// Namespace to restrict configuration from the file - namespace: Option, - - /// Format of file (which dictates what driver to use); Defauts to TOML. - format: FileFormat, - - /// A required File will error if it cannot be found - required: bool, -} - -impl File { - pub fn from_str(s: &str, format: FileFormat) -> File { - File { - format: format, - required: true, - namespace: None, - source: FileSourceString(s.into()), - } - } -} - -impl File { - pub fn new(name: &str, format: FileFormat) -> File { - File { - format: format, - required: true, - namespace: None, - source: FileSourceFile { - name: name.into(), - path: None, - }, - } - } -} - -impl File { - pub fn required(self, required: bool) -> File { - File { required: required, ..self } - } - - pub fn namespace(self, namespace: &str) -> Self { - File { namespace: Some(namespace.into()), ..self } - } - - // Build normally and return error on failure - fn try_build(&self) -> Result, Box> { - self.source.try_build(self.format, self.namespace.as_ref()) - } -} - -impl File { - pub fn path(self, path: &str) -> Self { - File { source: FileSourceFile { path: Some(path.into()), ..self.source }, ..self } - } -} - -impl SourceBuilder for File { - // Use try_build but only pass an error through if this source - // is required - fn build(&self) -> Result, Box> { - if self.required { - self.try_build() - } else { - self.try_build().or_else(|_| Ok(Box::new(nil::Nil {}))) - } - } -} -- cgit v1.2.3