Skip to main content

prns_config/reference/
parse.rs

1use crate::configobj;
2use crate::diagnostic::{ConfigDiagnostic, ConfigDiagnosticCode, ConfigErrors, ConfigReport};
3
4use super::interpret::interpret;
5use super::types::ReferenceConfig;
6use super::validation::{legacy_diagnostic, validate, ValidationResult};
7
8pub fn parse(input: &str) -> Result<ReferenceConfig, ConfigErrors> {
9    parse_named("config", input).map(|report| report.value)
10}
11
12pub fn parse_named(
13    source: impl Into<String>,
14    input: &str,
15) -> Result<ConfigReport<ReferenceConfig>, ConfigErrors> {
16    let source = source.into();
17    let parsed = match configobj::parse_located(input) {
18        Ok(parsed) => parsed,
19        Err(error) => {
20            let line = error.line();
21            return Err(ConfigErrors::new(vec![ConfigDiagnostic::new(
22                ConfigDiagnosticCode::Syntax,
23                source,
24                line,
25                "<document>",
26                None,
27                error.to_string(),
28                Some(
29                    "stock ConfigObj syntax with section headers and key = value entries"
30                        .to_string(),
31                ),
32                format!("correct the syntax on line {line}"),
33            )]));
34        }
35    };
36    let warnings = match validate(&source, &parsed.root, &parsed.locations) {
37        ValidationResult::Valid { warnings } => warnings.into_inner(),
38        ValidationResult::Invalid { errors, warnings } => {
39            return Err(ConfigErrors::new((*errors).with_warnings(warnings)));
40        }
41    };
42    let value = interpret(&parsed.root).map_err(|error| {
43        ConfigErrors::new(vec![legacy_diagnostic(&source, &parsed.locations, error)])
44    })?;
45    Ok(ConfigReport {
46        value,
47        warnings,
48        source,
49        locations: parsed.locations,
50    })
51}