From abe7f7624a02261cde994d5128d44c63fe65dd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Kot?= Date: Sat, 31 Jul 2021 16:40:52 +0200 Subject: Make File generic over Format and FileExtensions --- src/file/mod.rs | 48 +++++++++++++++++++++++++++++++---------------- src/file/source/file.rs | 29 +++++++++++++++++----------- src/file/source/mod.rs | 11 +++++++---- src/file/source/string.rs | 14 +++++++++----- 4 files changed, 66 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/file/mod.rs b/src/file/mod.rs index 2b15a1a..8d5b538 100644 --- a/src/file/mod.rs +++ b/src/file/mod.rs @@ -1,36 +1,43 @@ +pub mod extension; mod format; pub mod source; -pub mod extension; +use std::fmt::Debug; use std::path::{Path, PathBuf}; use crate::error::*; use crate::map::Map; use crate::source::Source; use crate::value::Value; +use crate::Format; pub use self::format::FileFormat; use self::source::FileSource; +pub use self::extension::FileExtensions; pub use self::source::file::FileSourceFile; pub use self::source::string::FileSourceString; #[derive(Clone, Debug)] -pub struct File +pub struct File where - T: FileSource, + F: Format + FileExtensions, + T: FileSource, { source: T, /// Format of file (which dictates what driver to use). - format: Option, + format: Option, /// A required File will error if it cannot be found required: bool, } -impl File { - pub fn from_str(s: &str, format: FileFormat) -> Self { +impl File +where + F: Format + FileExtensions + 'static, +{ + pub fn from_str(s: &str, format: F) -> Self { File { format: Some(format), required: true, @@ -39,15 +46,20 @@ impl File { } } -impl File { - pub fn new(name: &str, format: FileFormat) -> Self { +impl File +where + F: Format + FileExtensions + 'static, +{ + pub fn new(name: &str, format: F) -> Self { File { format: Some(format), required: true, source: source::file::FileSourceFile::new(name.into()), } } +} +impl File { /// Given the basename of a file, will attempt to locate a file by setting its /// extension to a registered format. pub fn with_name(name: &str) -> Self { @@ -59,7 +71,7 @@ impl File { } } -impl<'a> From<&'a Path> for File { +impl<'a> From<&'a Path> for File { fn from(path: &'a Path) -> Self { File { format: None, @@ -69,7 +81,7 @@ impl<'a> From<&'a Path> for File { } } -impl From for File { +impl From for File { fn from(path: PathBuf) -> Self { File { format: None, @@ -79,8 +91,12 @@ impl From for File { } } -impl File { - pub fn format(mut self, format: FileFormat) -> Self { +impl File +where + F: Format + FileExtensions + 'static, + T: FileSource, +{ + pub fn format(mut self, format: F) -> Self { self.format = Some(format); self } @@ -91,10 +107,10 @@ impl File { } } -impl Source for File +impl Source for File where - T: 'static, - T: Sync + Send, + F: Format + FileExtensions + Debug + Clone + Send + Sync + 'static, + T: Sync + Send + FileSource + 'static, { fn clone_into_box(&self) -> Box { Box::new((*self).clone()) @@ -104,7 +120,7 @@ where // Coerce the file contents to a string let (uri, contents, format) = match self .source - .resolve(self.format) + .resolve(self.format.clone()) .map_err(|err| ConfigError::Foreign(err)) { Ok((uri, contents, format)) => (uri, contents, format), diff --git a/src/file/source/file.rs b/src/file/source/file.rs index 75634dd..0feb447 100644 --- a/src/file/source/file.rs +++ b/src/file/source/file.rs @@ -6,7 +6,8 @@ use std::iter::Iterator; use std::path::{Path, PathBuf}; use crate::file::format::ALL_EXTENSIONS; -use crate::file::{FileFormat, FileSource}; +use crate::file::{FileExtensions, FileSource}; +use crate::Format; /// Describes a file sourced from a file #[derive(Clone, Debug)] @@ -20,15 +21,18 @@ impl FileSourceFile { FileSourceFile { name } } - fn find_file( + fn find_file( &self, - format_hint: Option, - ) -> Result<(PathBuf, FileFormat), Box> { + format_hint: Option, + ) -> Result<(PathBuf, Box), Box> + where + F: FileExtensions + Format + 'static, + { // First check for an _exact_ match let mut filename = env::current_dir()?.as_path().join(self.name.clone()); if filename.is_file() { return match format_hint { - Some(format) => Ok((filename, format)), + Some(format) => Ok((filename, Box::new(format))), None => { for (format, extensions) in ALL_EXTENSIONS.iter() { if extensions.contains( @@ -38,7 +42,7 @@ impl FileSourceFile { .to_string_lossy() .as_ref(), ) { - return Ok((filename, *format)); + return Ok((filename, Box::new(*format))); } } @@ -59,7 +63,7 @@ impl FileSourceFile { filename.set_extension(ext); if filename.is_file() { - return Ok((filename, format)); + return Ok((filename, Box::new(format))); } } } @@ -70,7 +74,7 @@ impl FileSourceFile { filename.set_extension(ext); if filename.is_file() { - return Ok((filename, *format)); + return Ok((filename, Box::new(*format))); } } } @@ -87,11 +91,14 @@ impl FileSourceFile { } } -impl FileSource for FileSourceFile { +impl FileSource for FileSourceFile +where + F: Format + FileExtensions + 'static, +{ fn resolve( &self, - format_hint: Option, - ) -> Result<(Option, String, FileFormat), Box> { + format_hint: Option, + ) -> Result<(Option, String, Box), Box> { // Find file let (filename, format) = self.find_file(format_hint)?; diff --git a/src/file/source/mod.rs b/src/file/source/mod.rs index 3b42a55..4a8877b 100644 --- a/src/file/source/mod.rs +++ b/src/file/source/mod.rs @@ -4,12 +4,15 @@ pub mod string; use std::error::Error; use std::fmt::Debug; -use crate::file::FileFormat; +use crate::{file::FileExtensions, Format}; /// Describes where the file is sourced -pub trait FileSource: Debug + Clone { +pub trait FileSource: Debug + Clone +where + T: Format + FileExtensions, +{ fn resolve( &self, - format_hint: Option, - ) -> Result<(Option, String, FileFormat), Box>; + format_hint: Option, + ) -> Result<(Option, String, Box), Box>; } diff --git a/src/file/source/string.rs b/src/file/source/string.rs index 2fede45..9bec751 100644 --- a/src/file/source/string.rs +++ b/src/file/source/string.rs @@ -1,6 +1,7 @@ use std::error::Error; -use crate::file::{FileFormat, FileSource}; +use crate::file::{FileExtensions, FileSource}; +use crate::Format; /// Describes a file sourced from a string #[derive(Clone, Debug)] @@ -12,15 +13,18 @@ impl<'a> From<&'a str> for FileSourceString { } } -impl FileSource for FileSourceString { +impl FileSource for FileSourceString +where + F: Format + FileExtensions + 'static, +{ fn resolve( &self, - format_hint: Option, - ) -> Result<(Option, String, FileFormat), Box> { + format_hint: Option, + ) -> Result<(Option, String, Box), Box> { Ok(( None, self.0.clone(), - format_hint.expect("from_str requires a set file format"), + Box::new(format_hint.expect("from_str requires a set file format")), )) } } -- cgit v1.2.3