hemtt_preprocessor/
resolver.rs

1use std::path::PathBuf;
2
3use hemtt_tokens::Token;
4
5use crate::{Context, Error};
6
7/// A trait for resolving includes
8pub trait Resolver {
9    /// Find the path to an included file
10    ///
11    /// # Errors
12    /// [`Error::IncludeNotFound`] if the file is not found
13    fn find_include(
14        &self,
15        context: &Context,
16        root: &str,
17        from: &str,
18        to: &str,
19        source: Vec<Token>,
20    ) -> Result<(PathBuf, String), Error>;
21}
22
23/// Built-in include resolvers
24pub mod resolvers {
25    use std::{
26        io::Read,
27        path::{Path, PathBuf},
28    };
29
30    use hemtt_tokens::Token;
31
32    use crate::Error;
33
34    use super::Resolver;
35
36    /// A resolver that only follows relative paths
37    pub struct LocalResolver;
38    impl LocalResolver {
39        #[must_use]
40        /// Create a new `LocalResolver`
41        pub const fn new() -> Self {
42            Self
43        }
44    }
45    impl Resolver for LocalResolver {
46        fn find_include(
47            &self,
48            _: &crate::Context,
49            _: &str,
50            from: &str,
51            to: &str,
52            _source: Vec<Token>,
53        ) -> Result<(PathBuf, String), Error> {
54            let mut path = Path::new(from).parent().unwrap().to_path_buf();
55            path.push(to);
56            let mut file = std::fs::File::open(&path)?;
57            let mut content = String::new();
58            file.read_to_string(&mut content)?;
59            Ok((path, content))
60        }
61    }
62
63    /// A resolver that does not resolve includes
64    pub struct NoResolver;
65    impl NoResolver {
66        #[must_use]
67        /// Create a new `NoResolver`
68        pub const fn new() -> Self {
69            Self
70        }
71    }
72    impl Resolver for NoResolver {
73        fn find_include(
74            &self,
75            context: &crate::Context,
76            _: &str,
77            _: &str,
78            _: &str,
79            source: Vec<Token>,
80        ) -> Result<(PathBuf, String), Error> {
81            Err(Error::ResolveWithNoResolver {
82                token: Box::new(source.first().unwrap().clone()),
83                trace: context.trace(),
84            })
85        }
86    }
87}