Skip to main content

xidl_parser/hir/
include.rs

1use crate::parser::IncludeResolver;
2use std::fs;
3use std::path::{Path, PathBuf};
4
5pub struct FsIncludeResolver;
6
7impl IncludeResolver for FsIncludeResolver {
8    fn resolve(
9        &mut self,
10        parent_path: Option<&str>,
11        path: &str,
12    ) -> crate::error::ParserResult<(String, String)> {
13        let parent = parent_path.map(Path::new).unwrap_or_else(|| Path::new("."));
14        let base = parent.parent().unwrap_or_else(|| Path::new("."));
15        let resolved_path = normalize_path(&base.join(path));
16
17        if !resolved_path.is_file() {
18            return Err(crate::error::ParseError::Message(format!(
19                "include path '{}' does not exist",
20                resolved_path.display()
21            )));
22        }
23
24        let content = fs::read_to_string(&resolved_path).map_err(|err| {
25            crate::error::ParseError::Message(format!(
26                "failed to read include '{}': {err}",
27                resolved_path.display()
28            ))
29        })?;
30
31        Ok((resolved_path.display().to_string(), content))
32    }
33}
34
35pub(crate) fn normalize_path(path: &Path) -> PathBuf {
36    let path = if path.is_absolute() {
37        path.to_path_buf()
38    } else {
39        std::env::current_dir()
40            .unwrap_or_else(|_| PathBuf::from("."))
41            .join(path)
42    };
43    fs::canonicalize(&path).unwrap_or(path)
44}