summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRadosław Kot <rdkt13@gmail.com>2021-07-31 16:40:52 +0200
committerRadosław Kot <rdkt13@gmail.com>2021-10-23 16:58:41 +0200
commitabe7f7624a02261cde994d5128d44c63fe65dd60 (patch)
tree9998f76719a0a35b956952522fac22c1309fea81
parent0cf715faf39ce0ac28e228eeb4874c374e1f0594 (diff)
Make File generic over Format and FileExtensions
-rw-r--r--src/file/mod.rs48
-rw-r--r--src/file/source/file.rs29
-rw-r--r--src/file/source/mod.rs11
-rw-r--r--src/file/source/string.rs14
4 files changed, 66 insertions, 36 deletions
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<T>
+pub struct File<T, F>
where
- T: FileSource,
+ F: Format + FileExtensions,
+ T: FileSource<F>,
{
source: T,
/// Format of file (which dictates what driver to use).
- format: Option<FileFormat>,
+ format: Option<F>,
/// A required File will error if it cannot be found
required: bool,
}
-impl File<source::string::FileSourceString> {
- pub fn from_str(s: &str, format: FileFormat) -> Self {
+impl<F> File<source::string::FileSourceString, F>
+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<source::string::FileSourceString> {
}
}
-impl File<source::file::FileSourceFile> {
- pub fn new(name: &str, format: FileFormat) -> Self {
+impl<F> File<source::file::FileSourceFile, F>
+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<source::file::FileSourceFile, FileFormat> {
/// 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<source::file::FileSourceFile> {
}
}
-impl<'a> From<&'a Path> for File<source::file::FileSourceFile> {
+impl<'a> From<&'a Path> for File<source::file::FileSourceFile, FileFormat> {
fn from(path: &'a Path) -> Self {
File {
format: None,
@@ -69,7 +81,7 @@ impl<'a> From<&'a Path> for File<source::file::FileSourceFile> {
}
}
-impl From<PathBuf> for File<source::file::FileSourceFile> {
+impl From<PathBuf> for File<source::file::FileSourceFile, FileFormat> {
fn from(path: PathBuf) -> Self {
File {
format: None,
@@ -79,8 +91,12 @@ impl From<PathBuf> for File<source::file::FileSourceFile> {
}
}
-impl<T: FileSource> File<T> {
- pub fn format(mut self, format: FileFormat) -> Self {
+impl<T, F> File<T, F>
+where
+ F: Format + FileExtensions + 'static,
+ T: FileSource<F>,
+{
+ pub fn format(mut self, format: F) -> Self {
self.format = Some(format);
self
}
@@ -91,10 +107,10 @@ impl<T: FileSource> File<T> {
}
}
-impl<T: FileSource> Source for File<T>
+impl<T, F> Source for File<T, F>
where
- T: 'static,
- T: Sync + Send,
+ F: Format + FileExtensions + Debug + Clone + Send + Sync + 'static,
+ T: Sync + Send + FileSource<F> + 'static,
{
fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
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<F>(
&self,
- format_hint: Option<FileFormat>,
- ) -> Result<(PathBuf, FileFormat), Box<dyn Error + Send + Sync>> {
+ format_hint: Option<F>,
+ ) -> Result<(PathBuf, Box<dyn Format>), Box<dyn Error + Send + Sync>>
+ 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<F> FileSource<F> for FileSourceFile
+where
+ F: Format + FileExtensions + 'static,
+{
fn resolve(
&self,
- format_hint: Option<FileFormat>,
- ) -> Result<(Option<String>, String, FileFormat), Box<dyn Error + Send + Sync>> {
+ format_hint: Option<F>,
+ ) -> Result<(Option<String>, String, Box<dyn Format>), Box<dyn Error + Send + Sync>> {
// 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<T>: Debug + Clone
+where
+ T: Format + FileExtensions,
+{
fn resolve(
&self,
- format_hint: Option<FileFormat>,
- ) -> Result<(Option<String>, String, FileFormat), Box<dyn Error + Send + Sync>>;
+ format_hint: Option<T>,
+ ) -> Result<(Option<String>, String, Box<dyn Format>), Box<dyn Error + Send + Sync>>;
}
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<F> FileSource<F> for FileSourceString
+where
+ F: Format + FileExtensions + 'static,
+{
fn resolve(
&self,
- format_hint: Option<FileFormat>,
- ) -> Result<(Option<String>, String, FileFormat), Box<dyn Error + Send + Sync>> {
+ format_hint: Option<F>,
+ ) -> Result<(Option<String>, String, Box<dyn Format>), Box<dyn Error + Send + Sync>> {
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")),
))
}
}