From 8bae9a8fab523668e9aea96e4f32cec21e22998a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 24 Mar 2019 16:25:37 +0100 Subject: Parser import hash and headers --- dhall/src/binary.rs | 35 ++++++++++++++++++++++++++++++----- dhall/src/imports.rs | 2 +- dhall/tests/parser.rs | 2 +- dhall_core/src/import.rs | 18 ++++++++++++++---- dhall_core/src/parser.rs | 31 +++++++++++++++++++------------ dhall_core/src/printer.rs | 23 +++++++++++++++++++++-- 6 files changed, 86 insertions(+), 25 deletions(-) diff --git a/dhall/src/binary.rs b/dhall/src/binary.rs index a028e82..eb96da2 100644 --- a/dhall/src/binary.rs +++ b/dhall/src/binary.rs @@ -179,11 +179,26 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result { .collect::>()?, ))) } - [U64(24), _hash, U64(mode), U64(scheme), rest..] => { + [U64(24), hash, U64(mode), U64(scheme), rest..] => { let mode = match mode { 1 => ImportMode::RawText, _ => ImportMode::Code, }; + let hash = match hash { + Null => None, + Array(vec) => match vec.as_slice() { + [String(protocol), String(hash)] => Some(Hash { + protocol: protocol.clone(), + hash: hash.clone(), + }), + _ => Err(DecodeError::WrongFormatError( + "import/hash".to_owned(), + ))?, + }, + _ => Err(DecodeError::WrongFormatError( + "import/hash".to_owned(), + ))?, + }; let mut rest = rest.iter(); let location = match scheme { 0 | 1 => { @@ -191,8 +206,18 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result { 0 => Scheme::HTTP, _ => Scheme::HTTPS, }; - let _headers = match rest.next() { - Some(Null) => (), + let headers = match rest.next() { + Some(Null) => None, + Some(x) => { + match cbor_value_to_dhall(&x)?.as_ref() { + Embed(import) => Some(Box::new( + import.location_hashed.clone(), + )), + _ => Err(DecodeError::WrongFormatError( + "import/remote/headers".to_owned(), + ))?, + } + } _ => Err(DecodeError::WrongFormatError( "import/remote/headers".to_owned(), ))?, @@ -224,6 +249,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result { authority, path, query, + headers, }) } 2 | 3 | 4 | 5 => { @@ -263,8 +289,7 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result { }; Embed(Import { mode, - hash: None, - location, + location_hashed: ImportHashed { hash, location }, }) } [U64(25), bindings..] => { diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs index 8a2edce..8df4e97 100644 --- a/dhall/src/imports.rs +++ b/dhall/src/imports.rs @@ -29,7 +29,7 @@ fn resolve_import( let cwd = match root { LocalDir(cwd) => cwd, }; - match &import.location { + match &import.location_hashed.location { Local(prefix, path) => { let path = match prefix { Parent => cwd.parent().unwrap().join(path), diff --git a/dhall/tests/parser.rs b/dhall/tests/parser.rs index 5f57068..1db8d33 100644 --- a/dhall/tests/parser.rs +++ b/dhall/tests/parser.rs @@ -42,7 +42,7 @@ parser_success!(spec_parser_success_multilet, "multilet"); parser_success!(spec_parser_success_natural, "natural"); parser_success!(spec_parser_success_nestedBlockComment, "nestedBlockComment"); parser_success!(spec_parser_success_operators, "operators"); -// parser_success!(spec_parser_success_parenthesizeUsing, "parenthesizeUsing"); +parser_success!(spec_parser_success_parenthesizeUsing, "parenthesizeUsing"); parser_success!(spec_parser_success_pathTermination, "pathTermination"); parser_success!(spec_parser_success_paths, "paths"); parser_success!(spec_parser_success_quotedLabel, "quotedLabel"); diff --git a/dhall_core/src/import.rs b/dhall_core/src/import.rs index 21bd370..f039953 100644 --- a/dhall_core/src/import.rs +++ b/dhall_core/src/import.rs @@ -28,7 +28,7 @@ pub struct URL { pub authority: String, pub path: PathBuf, pub query: Option, - // pub headers: Option, + pub headers: Option>, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -44,11 +44,21 @@ pub enum ImportMode { RawText, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Hash { + pub protocol: String, + pub hash: String, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ImportHashed { + pub location: ImportLocation, + pub hash: Option, +} + /// Reference to an external resource #[derive(Debug, Clone, PartialEq, Eq)] pub struct Import { pub mode: ImportMode, - pub location: ImportLocation, - // TODO - pub hash: Option<()>, + pub location_hashed: ImportHashed, } diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs index 4f26b0f..3d5a761 100644 --- a/dhall_core/src/parser.rs +++ b/dhall_core/src/parser.rs @@ -431,12 +431,14 @@ make_parser! { authority: auth, path: p, query: None, + headers: None, }, [scheme(sch), authority(auth), path(p), query(q)] => URL { scheme: sch, authority: auth, path: p, query: Some(q), + headers: None, }, )); @@ -444,9 +446,10 @@ make_parser! { rule!(query; captured_str!(s) => s.to_owned()); - // TODO: headers rule!(http; children!( - [http_raw(url)] => url + [http_raw(url)] => url, + [http_raw(url), import_hashed(import_hashed)] => + URL { headers: Some(Box::new(import_hashed)), ..url }, )); rule!(env; children!( @@ -458,7 +461,6 @@ make_parser! { rule!(missing<()>; captured_str!(_) => ()); - // TODO: other import types rule!(import_type; children!( [missing(_)] => { ImportLocation::Missing @@ -474,9 +476,16 @@ make_parser! { }, )); - rule!(import_hashed<(ImportLocation, Option<()>)>; children!( - // TODO: handle hash - [import_type(import)] => (import, None) + rule!(hash; captured_str!(s) => + Hash { + protocol: s.trim()[..6].to_owned(), + hash: s.trim()[7..].to_owned(), + } + ); + + rule!(import_hashed; children!( + [import_type(location)] => ImportHashed { location, hash: None }, + [import_type(location), hash(hash)] => ImportHashed { location, hash: Some(hash) }, )); rule_group!(expression); @@ -484,18 +493,16 @@ make_parser! { rule!(Text<()>; captured_str!(_) => ()); rule!(import as expression; children!( - [import_hashed((location, hash))] => { + [import_hashed(location_hashed)] => { bx(Expr::Embed(Import { mode: ImportMode::Code, - hash, - location, + location_hashed })) }, - [import_hashed((location, hash)), Text(_)] => { + [import_hashed(location_hashed), Text(_)] => { bx(Expr::Embed(Import { mode: ImportMode::RawText, - hash, - location, + location_hashed })) }, )); diff --git a/dhall_core/src/printer.rs b/dhall_core/src/printer.rs index 9525904..1d1b063 100644 --- a/dhall_core/src/printer.rs +++ b/dhall_core/src/printer.rs @@ -326,12 +326,16 @@ impl Display for Label { } } -impl Display for Import { +impl Display for Hash { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}:{}", self.protocol, self.hash) + } +} +impl Display for ImportHashed { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { use std::path::PathBuf; use FilePrefix::*; use ImportLocation::*; - use ImportMode::*; let quoted = |s: &str| -> String { if s.chars().all(|c| c.is_ascii_alphanumeric()) { s.to_owned() @@ -364,6 +368,9 @@ impl Display for Import { if let Some(q) = &url.query { write!(f, "?{}", q)? } + if let Some(h) = &url.headers { + write!(f, " using ({})", h)? + } } Env(e) => { write!(f, "env:{}", quoted(e))?; @@ -372,6 +379,18 @@ impl Display for Import { write!(f, "missing")?; } } + if let Some(hash) = &self.hash { + write!(f, " ")?; + hash.fmt(f)?; + } + Ok(()) + } +} + +impl Display for Import { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + self.location_hashed.fmt(f)?; + use ImportMode::*; match self.mode { Code => {} RawText => write!(f, " as Text")?, -- cgit v1.2.3