ddoc/
files.rs

1use {
2    crate::*,
3    serde::de::DeserializeOwned,
4    std::{
5        fs::File,
6        io::BufReader,
7        path::Path,
8    },
9};
10
11/// Deserialize an object from a JSON, TOML, or HJSON file.
12///
13/// # Errors
14/// Return `DdError::Read` on file read errors, `DdError::UnsupportedFileFormat`
15/// if the file extension is not supported, and deserialization errors
16/// as appropriate.
17pub fn read_file<T, P: AsRef<Path>>(path: P) -> DdResult<T>
18where
19    T: DeserializeOwned,
20{
21    let path = path.as_ref();
22    let file = File::open(path).map_err(|error| DdError::Read {
23        path: path.to_owned(),
24        error,
25    })?;
26    let reader = BufReader::new(file);
27    let obj = match path.extension().and_then(|s| s.to_str()) {
28        Some("hjson") => deser_hjson::from_reader(reader)?,
29        Some("json") => serde_json::from_reader(reader)?,
30        Some("toml") => {
31            let toml = std::io::read_to_string(reader)?;
32            toml::from_str(&toml)?
33        }
34        _ => return Err(DdError::UnsupportedFileFormat(path.to_owned())),
35    };
36    Ok(obj)
37}
38
39/// Search direct subdirectories of `parent` for a ddoc project
40/// (a directory containing a valid `ddoc.hjson` file).
41pub fn project_subdirectory(parent: &Path) -> Option<std::path::PathBuf> {
42    let read_dir = std::fs::read_dir(parent).ok()?;
43    for entry in read_dir.flatten() {
44        let path = entry.path();
45        if path.is_dir() && Project::load(&path).is_ok() {
46            return Some(path);
47        }
48    }
49    None
50}