Skip to main content

nex_pkg/
document.rs

1use std::path::{Path, PathBuf};
2
3use anyhow::{bail, Context, Result};
4use serde::de::DeserializeOwned;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum DocumentFormat {
8    Pkl,
9    TomlCompat,
10}
11
12#[derive(Debug, Clone)]
13pub struct LoadedDocument<T> {
14    pub value: T,
15    pub format: DocumentFormat,
16    pub path: PathBuf,
17}
18
19impl<T> LoadedDocument<T> {
20    pub fn is_canonical(&self) -> bool {
21        self.format == DocumentFormat::Pkl
22    }
23}
24
25pub fn load_document<T>(path: &Path, description: &str) -> Result<LoadedDocument<T>>
26where
27    T: DeserializeOwned,
28{
29    match path.extension().and_then(|ext| ext.to_str()) {
30        Some("pkl") => {
31            let value = crate::pkl::evaluate_json(path)
32                .and_then(|json| serde_json::from_value(json).context("decoding evaluated Pkl JSON"))
33                .with_context(|| format!("loading canonical Pkl {description} {}", path.display()))?;
34            Ok(LoadedDocument {
35                value,
36                format: DocumentFormat::Pkl,
37                path: path.to_path_buf(),
38            })
39        }
40        Some("toml") => {
41            let content = std::fs::read_to_string(path)
42                .with_context(|| format!("reading compatibility TOML {description} {}", path.display()))?;
43            let value = toml::from_str(&content)
44                .with_context(|| format!("parsing compatibility TOML {description} {}", path.display()))?;
45            Ok(LoadedDocument {
46                value,
47                format: DocumentFormat::TomlCompat,
48                path: path.to_path_buf(),
49            })
50        }
51        Some(ext) => bail!(
52            "unsupported {description} extension .{ext}; canonical Nex documents use .pkl (.toml is compatibility/interchange)"
53        ),
54        None => bail!(
55            "{description} path must have an extension; canonical Nex documents use .pkl (.toml is compatibility/interchange)"
56        ),
57    }
58}