systemd-boot-conf 0.2.2

Managing the systemd-boot loader configuration
Documentation
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::path::Path;

#[derive(Debug, Error)]
pub enum LoaderError {
    #[error("error reading line in loader conf")]
    Line(#[source] io::Error),
    #[error("loader conf is not a file")]
    NotAFile,
    #[error("default was defined without a value")]
    NoValueForDefault,
    #[error("timeout was defined without a value")]
    NoValueForTimeout,
    #[error("error opening loader file")]
    Open(#[source] io::Error),
    #[error("timeout was defined with a value ({}) which is not a number", _0)]
    TimeoutNaN(String),
}

#[derive(Debug, Default, Clone)]
pub struct LoaderConf {
    pub default: Option<Box<str>>,
    pub timeout: Option<u32>,
}

impl LoaderConf {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, LoaderError> {
        let path = path.as_ref();

        let mut loader = LoaderConf::default();
        if !path.exists() {
            return Ok(loader);
        }

        if !path.is_file() {
            return Err(LoaderError::NotAFile);
        }

        let file = File::open(path).map_err(LoaderError::Open)?;

        for line in BufReader::new(file).lines() {
            let line = line.map_err(LoaderError::Line)?;
            let mut fields = line.split_whitespace();
            match fields.next() {
                Some("default") => match fields.next() {
                    Some(default) => loader.default = Some(default.into()),
                    None => return Err(LoaderError::NoValueForDefault),
                },
                Some("timeout") => match fields.next() {
                    Some(timeout) => {
                        if let Ok(timeout) = timeout.parse::<u32>() {
                            loader.timeout = Some(timeout);
                        } else {
                            return Err(LoaderError::TimeoutNaN(timeout.into()));
                        }
                    }
                    None => return Err(LoaderError::NoValueForTimeout),
                },
                _ => (),
            }
        }

        Ok(loader)
    }
}