use crate::syntax::trivial_result; /// The beginning of a file path which anchors subsequent path components #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum FilePrefix { /// Absolute path Absolute, /// Path relative to . Here, /// Path relative to .. Parent, /// Path relative to ~ Home, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FilePath { pub file_path: Vec, } /// The location of import (i.e. local vs. remote vs. environment) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ImportTarget { Local(FilePrefix, FilePath), Remote(URL), Env(String), Missing, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct URL { pub scheme: Scheme, pub authority: String, pub path: FilePath, pub query: Option, pub headers: Option, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Scheme { HTTP, HTTPS, } /// How to interpret the import's contents (i.e. as Dhall code or raw text) #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum ImportMode { Code, RawText, Location, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Hash { SHA256(Box<[u8]>), } /// Reference to an external resource #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Import { pub mode: ImportMode, pub location: ImportTarget, pub hash: Option, } impl URL { pub fn traverse_ref<'a, Err, SE2>( &'a self, f: impl FnOnce(&'a SE) -> Result, ) -> Result, Err> { let headers = self.headers.as_ref().map(f).transpose()?; Ok(URL { scheme: self.scheme, authority: self.authority.clone(), path: self.path.clone(), query: self.query.clone(), headers, }) } pub fn map_ref<'a, SE2>( &'a self, f: impl FnOnce(&'a SE) -> SE2, ) -> URL { trivial_result(self.traverse_ref(|x| Ok(f(x)))) } } impl ImportTarget { pub fn traverse_ref<'a, Err, SE2>( &'a self, f: impl FnOnce(&'a SE) -> Result, ) -> Result, Err> { use ImportTarget::*; Ok(match self { Local(prefix, path) => Local(*prefix, path.clone()), Remote(url) => Remote(url.traverse_ref(f)?), Env(env) => Env(env.clone()), Missing => Missing, }) } pub fn map_ref<'a, SE2>( &'a self, f: impl FnOnce(&'a SE) -> SE2, ) -> ImportTarget { trivial_result(self.traverse_ref(|x| Ok(f(x)))) } } impl Import { pub fn traverse_ref<'a, Err, SE2>( &'a self, f: impl FnOnce(&'a SE) -> Result, ) -> Result, Err> { Ok(Import { mode: self.mode, location: self.location.traverse_ref(f)?, hash: self.hash.clone(), }) } pub fn map_ref<'a, SE2>( &'a self, f: impl FnOnce(&'a SE) -> SE2, ) -> Import { trivial_result(self.traverse_ref(|x| Ok(f(x)))) } }