1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::rc::Rc;
use std::io::{Read, Write};
use std::io::stderr;
use std::fs::File;
use std::path::Path;
use std::sync::mpsc::channel;
use rustc_serialize::{Decodable};

use super::ast;
pub use super::errors::Error;
use super::parser::parse;
use super::decode::YamlDecoder;
use super::validate::Validator;


pub fn parse_config<T: Decodable, P: AsRef<Path>>(
    filename: P, validator: &Validator, options: ast::Options)
    -> Result<T, String>
{
    let filename = filename.as_ref();
    let mut file = try!(File::open(filename)
        .map_err(|e| format!("Error opening config {}: {}",
            filename.display(), e)));
    let mut body = String::new();
    try!(file.read_to_string(&mut body)
        .map_err(|e| format!("Error reading config {}: {}",
            filename.display(), e)));
    let (ast, mut warnings) = try!(parse(
            Rc::new(format!("{}", filename.display())),
            &body,
            |doc| { ast::process(options, doc) })
        .map_err(|e| format!("Error parsing config {}: {}",
            filename.display(), e)));
    let (ast, nwarn) = validator.validate(ast);
    warnings.extend(nwarn.into_iter());
    let (tx, rx) = channel();
    let res = {
        let mut dec = YamlDecoder::new(ast, tx);
        Decodable::decode(&mut dec)
    };
    warnings.extend(rx.iter());
    if options.print_warnings {
        let mut err = stderr();
        for warning in warnings.iter() {
            (writeln!(&mut err, "config: {}", warning)).ok();
        }
    }
    match res {
        Ok(val) => {
            if warnings.len() > 0 {
                return Err(format!("Multiple errors in configuration file {}",
                    filename.display()));
            }
            return Ok(val);
        }
        Err(err) => {
                return Err(format!("Fatal error in {}: {}",
                    filename.display(), err));
        }
    }
}