Skip to main content

rvaultlib/typedetect/
mod.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub enum FileFormat {
3    Json,
4    Yaml,
5    /// A raw ansible-vault blob produced by `--level 0` or `ansible-vault encrypt`.
6    Vault,
7}
8
9/// Detect the format of a file.
10/// Tries the file extension first (fast path), then falls back to content-based detection.
11pub fn detect_format(file: &str) -> Result<FileFormat, Box<dyn std::error::Error>> {
12    match std::path::Path::new(file)
13        .extension()
14        .and_then(|e| e.to_str())
15    {
16        Some("json") => return Ok(FileFormat::Json),
17        Some("yaml") | Some("yml") => return Ok(FileFormat::Yaml),
18        _ => {}
19    }
20
21    let content = std::fs::read_to_string(file)?;
22    if content.starts_with("$ANSIBLE_VAULT;") {
23        return Ok(FileFormat::Vault);
24    }
25    if serde_json::from_str::<serde_json::Value>(&content).is_ok() {
26        return Ok(FileFormat::Json);
27    }
28    if serde_yaml::from_str::<serde_yaml::Value>(&content).is_ok() {
29        return Ok(FileFormat::Yaml);
30    }
31
32    Err(format!("Cannot detect format of file '{}': not valid JSON or YAML", file).into())
33}