summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/src/phase/binary.rs10
-rw-r--r--dhall/src/phase/resolve.rs70
-rw-r--r--dhall_syntax/src/core/import.rs75
-rw-r--r--dhall_syntax/src/parser.rs6
4 files changed, 81 insertions, 80 deletions
diff --git a/dhall/src/phase/binary.rs b/dhall/src/phase/binary.rs
index 16e7ce9..3c45e81 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};
@@ -279,7 +279,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(
@@ -287,7 +287,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,
@@ -306,7 +306,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(
@@ -314,7 +314,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 5bde68a..54a0f27 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>;
@@ -105,6 +106,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 5e0ff6c..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 {
- // ───────────────────
- // 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 b70a236..52b3760 100644
--- a/dhall_syntax/src/parser.rs
+++ b/dhall_syntax/src/parser.rs
@@ -729,7 +729,7 @@ make_parser! {
[scheme(sch), authority(auth), path(file_path)] => URL {
scheme: sch,
authority: auth,
- path: File { file_path },
+ path: FilePath { file_path },
query: None,
headers: None,
},
@@ -737,7 +737,7 @@ make_parser! {
URL {
scheme: sch,
authority: auth,
- path: File { file_path },
+ path: FilePath { file_path },
query: Some(q),
headers: None,
}
@@ -794,7 +794,7 @@ make_parser! {
ImportLocation::Remote(url)
},
[local((prefix, file_path))] => {
- ImportLocation::Local(prefix, File { file_path })
+ ImportLocation::Local(prefix, FilePath { file_path })
},
));