use serde::de::DeserializeOwned;
use crate::config::MergeStrategy;
use crate::domain::{Format, ParsedContent, RawContent, Result, Source, SourceError};
use super::Loader;
use crate::application::SourceLayer;
use crate::application::support::{
load_source_content, merge_contents, parse_raw_as_format, parse_raw_content,
};
impl Loader {
pub fn load_raw<S: Source>(&self, source: &S) -> Result<RawContent> {
source.validate()?;
source.load_raw()
}
pub fn load<S: Source>(&self, source: &S) -> Result<ParsedContent> {
load_source_content(source, self.default_format)
}
pub fn load_layer<S: Source>(&self, source: &S) -> Result<SourceLayer> {
let metadata = source.metadata();
Ok(SourceLayer {
priority: metadata.priority,
metadata,
registration_index: 0,
content: self.load(source)?,
})
}
pub fn load_layers<S: Source>(&self, sources: &[S]) -> Result<Vec<SourceLayer>> {
sources
.iter()
.enumerate()
.map(|(registration_index, source)| {
let metadata = source.metadata();
Ok(SourceLayer {
priority: metadata.priority,
metadata,
registration_index,
content: self.load(source)?,
})
})
.collect()
}
pub fn load_as<S: Source, T: DeserializeOwned>(&self, source: &S) -> Result<T> {
let content = self.load(source)?;
self.to_type(content)
}
pub fn parse(&self, raw: &RawContent, format: Format) -> Result<ParsedContent> {
parse_raw_as_format(raw, format)
}
pub fn parse_raw(
&self,
raw: &RawContent,
detected_format: Option<Format>,
) -> Result<ParsedContent> {
parse_raw_content(raw, detected_format, self.default_format)
}
pub fn merge(&self, contents: Vec<ParsedContent>) -> Result<ParsedContent> {
merge_contents(contents, self.merge_strategy())
}
pub fn to_type<T: DeserializeOwned>(&self, content: ParsedContent) -> Result<T> {
content.into_type()
}
pub fn load_multiple<S: Source>(&self, sources: &[S]) -> Result<ParsedContent> {
let mut contents = Vec::new();
let mut errors: Vec<(String, SourceError)> = Vec::new();
for source in sources {
match self.load(source) {
Ok(content) => contents.push(content),
Err(error) => {
if source.is_optional() && self.options.ignores_missing_optional() {
continue;
}
if self.options.is_fail_fast() {
return Err(error);
}
errors.push((source.display_name(), error));
}
}
}
if !errors.is_empty() && contents.is_empty() {
let error_messages: Vec<String> = errors
.into_iter()
.map(|(name, error)| format!("{name}: {error}"))
.collect();
return Err(SourceError::custom(&error_messages.join(", ")));
}
self.merge(contents)
}
const fn merge_strategy(&self) -> MergeStrategy {
self.options.merge_strategy
}
}