diff options
-rw-r--r-- | dhall/src/phase/.resolve.rs.swp | bin | 16384 -> 0 bytes | |||
-rw-r--r-- | dhall/src/phase/binary.rs | 10 | ||||
-rw-r--r-- | dhall/src/phase/resolve.rs | 70 | ||||
-rw-r--r-- | dhall_syntax/src/core/import.rs | 75 | ||||
-rw-r--r-- | dhall_syntax/src/parser.rs | 14 |
5 files changed, 85 insertions, 84 deletions
diff --git a/dhall/src/phase/.resolve.rs.swp b/dhall/src/phase/.resolve.rs.swp Binary files differdeleted file mode 100644 index 5314300..0000000 --- a/dhall/src/phase/.resolve.rs.swp +++ /dev/null diff --git a/dhall/src/phase/binary.rs b/dhall/src/phase/binary.rs index f271eb1..4831c7e 100644 --- a/dhall/src/phase/binary.rs +++ b/dhall/src/phase/binary.rs @@ -6,7 +6,7 @@ use std::vec; use dhall_syntax::map::DupTreeMap; use dhall_syntax::{ rc, Expr, ExprF, FilePrefix, Hash, Import, ImportLocation, ImportMode, - Integer, InterpolatedText, Label, Natural, Scheme, URL, V, File + Integer, InterpolatedText, Label, Natural, Scheme, URL, V, FilePath }; use crate::error::{DecodeError, EncodeError}; @@ -281,7 +281,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> { "import/remote/query".to_owned(), ))?, }; - let file_path: Vec<_> = rest + let file_path = rest .map(|s| match s.as_string() { Some(s) => Ok(s.clone()), None => Err(DecodeError::WrongFormatError( @@ -289,7 +289,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> { )), }) .collect::<Result<_, _>>()?; - let path = File { file_path }; + let path = FilePath { file_path }; ImportLocation::Remote(URL { scheme, authority, @@ -308,7 +308,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> { "import/local/prefix".to_owned(), ))?, }; - let file_path: Vec<_> = rest + let file_path = rest .map(|s| match s.as_string() { Some(s) => Ok(s.clone()), None => Err(DecodeError::WrongFormatError( @@ -316,7 +316,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result<DecodedExpr, DecodeError> { )), }) .collect::<Result<_, _>>()?; - let path = File { file_path }; + let path = FilePath { file_path }; ImportLocation::Local(prefix, path) } 6 => { diff --git a/dhall/src/phase/resolve.rs b/dhall/src/phase/resolve.rs index b10a7bd..4034a5c 100644 --- a/dhall/src/phase/resolve.rs +++ b/dhall/src/phase/resolve.rs @@ -3,6 +3,7 @@ use std::path::{Path, PathBuf}; use crate::error::{Error, ImportError}; use crate::phase::{Normalized, NormalizedExpr, Parsed, Resolved}; +use dhall_syntax::{FilePath, ImportLocation, URL}; type Import = dhall_syntax::Import<NormalizedExpr>; @@ -104,6 +105,75 @@ pub(crate) fn skip_resolve_expr( Ok(Resolved(expr)) } +pub trait Canonicalize { + fn canonicalize(&self) -> Self; +} + +impl Canonicalize for FilePath { + fn canonicalize(&self) -> FilePath { + let mut file_path = Vec::new(); + let mut file_path_components = self.file_path.clone().into_iter(); + + loop { + let component = file_path_components.next(); + match component.as_ref() { + // ─────────────────── + // canonicalize(ε) = ε + None => break, + + // canonicalize(directory₀) = directory₁ + // ─────────────────────────────────────── + // canonicalize(directory₀/.) = directory₁ + Some(c) if c == "." => continue, + + Some(c) if c == ".." => match file_path_components.next() { + // canonicalize(directory₀) = ε + // ──────────────────────────── + // canonicalize(directory₀/..) = /.. + None => file_path.push("..".to_string()), + + // canonicalize(directory₀) = directory₁/.. + // ────────────────────────────────────────────── + // canonicalize(directory₀/..) = directory₁/../.. + Some(ref c) if c == ".." => { + file_path.push("..".to_string()); + file_path.push("..".to_string()); + }, + + // canonicalize(directory₀) = directory₁/component + // ─────────────────────────────────────────────── ; If "component" is not + // canonicalize(directory₀/..) = directory₁ ; ".." + Some(_) => continue, + }, + + // canonicalize(directory₀) = directory₁ + // ───────────────────────────────────────────────────────── ; If no other + // canonicalize(directory₀/component) = directory₁/component ; rule matches + Some(c) => file_path.push(c.clone()), + } + } + + FilePath { file_path } + } +} + +impl<SE: Copy> Canonicalize for ImportLocation<SE> { + fn canonicalize(&self) -> ImportLocation<SE> { + match self { + ImportLocation::Local(prefix, file) => ImportLocation::Local(*prefix, file.canonicalize()), + ImportLocation::Remote(url) => ImportLocation::Remote(URL { + scheme: url.scheme, + authority: url.authority.clone(), + path: url.path.canonicalize(), + query: url.query.clone(), + headers: url.headers.clone(), + }), + ImportLocation::Env(name) => ImportLocation::Env(name.to_string()), + ImportLocation::Missing => ImportLocation::Missing, + } + } +} + #[cfg(test)] #[rustfmt::skip] mod spec_tests { diff --git a/dhall_syntax/src/core/import.rs b/dhall_syntax/src/core/import.rs index ef696b9..cc38bb0 100644 --- a/dhall_syntax/src/core/import.rs +++ b/dhall_syntax/src/core/import.rs @@ -12,14 +12,14 @@ pub enum FilePrefix { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct File { +pub struct FilePath { pub file_path: Vec<String>, } /// The location of import (i.e. local vs. remote vs. environment) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ImportLocation<SubExpr> { - Local(FilePrefix, File), + Local(FilePrefix, FilePath), Remote(URL<SubExpr>), Env(String), Missing, @@ -29,7 +29,7 @@ pub enum ImportLocation<SubExpr> { pub struct URL<SubExpr> { pub scheme: Scheme, pub authority: String, - pub path: File, + pub path: FilePath, pub query: Option<String>, pub headers: Option<SubExpr>, } @@ -104,72 +104,3 @@ impl<SE> Import<SE> { }) } } - -pub trait Canonicalize { - fn canonicalize(&self) -> Self; -} - -impl Canonicalize for File { - fn canonicalize(&self) -> File { - let mut file_path = Vec::new(); - let mut file_path_components = self.file_path.clone().into_iter(); - - loop { - let component = file_path_components.next(); - match component.as_ref() { - // ─────────────────── - // canonicalize(ε) = ε - None => break, - - // canonicalize(directory₀) = directory₁ - // ─────────────────────────────────────── - // canonicalize(directory₀/.) = directory₁ - Some(c) if c == "." => continue, - - Some(c) if c == ".." => match file_path_components.next() { - // canonicalize(directory₀) = ε - // ──────────────────────────── - // canonicalize(directory₀/..) = /.. - None => file_path.push("..".to_string()), - - // canonicalize(directory₀) = directory₁/.. - // ────────────────────────────────────────────── - // canonicalize(directory₀/..) = directory₁/../.. - Some(ref c) if c == ".." => { - file_path.push("..".to_string()); - file_path.push("..".to_string()); - }, - - // canonicalize(directory₀) = directory₁/component - // ─────────────────────────────────────────────── ; If "component" is not - // canonicalize(directory₀/..) = directory₁ ; ".." - Some(_) => continue, - }, - - // canonicalize(directory₀) = directory₁ - // ───────────────────────────────────────────────────────── ; If no other - // canonicalize(directory₀/component) = directory₁/component ; rule matches - Some(c) => file_path.push(c.clone()), - } - } - - File { file_path } - } -} - -impl<SubExpr: Copy> Canonicalize for ImportLocation<SubExpr> { - fn canonicalize(&self) -> ImportLocation<SubExpr> { - match self { - ImportLocation::Local(prefix, file) => ImportLocation::Local(*prefix, file.canonicalize()), - ImportLocation::Remote(url) => ImportLocation::Remote(URL { - scheme: url.scheme, - authority: url.authority.clone(), - path: url.path.canonicalize(), - query: url.query.clone(), - headers: url.headers.clone(), - }), - ImportLocation::Env(name) => ImportLocation::Env(name.to_string()), - ImportLocation::Missing => ImportLocation::Missing, - } - } -} diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index 40784ec..1262774 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -564,15 +564,15 @@ impl Parsers { }, )) } - fn path(input: ParseInput<Rule>) -> ParseResult<File> { + fn path(input: ParseInput<Rule>) -> ParseResult<FilePath> { Ok(parse_children!(input; [path_component(components)..] => { - File { file_path: components.collect() } + FilePath { file_path: components.collect() } } )) } - fn local(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, File)> { + fn local(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> { Ok(parse_children!(input; [parent_path(l)] => l, [here_path(l)] => l, @@ -581,24 +581,24 @@ impl Parsers { )) } - fn parent_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, File)> { + fn parent_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> { Ok(parse_children!(input; [path(p)] => (FilePrefix::Parent, p) )) } - fn here_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, File)> { + fn here_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> { Ok(parse_children!(input; [path(p)] => (FilePrefix::Here, p) )) } - fn home_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, File)> { + fn home_path(input: ParseInput<Rule>) -> ParseResult<(FilePrefix, FilePath)> { Ok(parse_children!(input; [path(p)] => (FilePrefix::Home, p) )) } fn absolute_path( input: ParseInput<Rule>, - ) -> ParseResult<(FilePrefix, File)> { + ) -> ParseResult<(FilePrefix, FilePath)> { Ok(parse_children!(input; [path(p)] => (FilePrefix::Absolute, p) )) |