diff --git a/cmp/Cargo.toml b/cmp/Cargo.toml index 5fc3e36..7f7243d 100644 --- a/cmp/Cargo.toml +++ b/cmp/Cargo.toml @@ -10,9 +10,9 @@ publish = false [dependencies] base64 = { git = "https://github.com/alicemaz/rust-base64" } data-encoding = { path = "../lib" } -libc = "0.2.21" -rustc-serialize = "0.3.23" -lazy_static = "0.2.8" +libc = "0.2" +rustc-serialize = "0.3" +lazy_static = "1" [build-dependencies] -cc = "1.0" +cc = "1" diff --git a/cmp/tests/lib.rs b/cmp/tests/lib.rs index 4216667..a7f80d8 100644 --- a/cmp/tests/lib.rs +++ b/cmp/tests/lib.rs @@ -41,7 +41,7 @@ fn difference() { let x = b"AAB="; assert_eq!(BASE64.decode(x).err().unwrap(), DecodeError { position: 2, kind: Trailing }); assert_eq!(x.from_base64().unwrap(), vec![0, 0]); - assert_eq!(base64::decode(x).unwrap(), vec![0, 0]); + assert!(base64::decode(x).is_err()); let x = b"AA\nB="; assert_eq!(BASE64.decode(x).err().unwrap(), DecodeError { position: 4, kind: Length }); assert_eq!(x.from_base64().unwrap(), vec![0, 0]); @@ -49,7 +49,7 @@ fn difference() { let x = b"AAB"; assert_eq!(BASE64.decode(x).err().unwrap(), DecodeError { position: 0, kind: Length }); assert_eq!(x.from_base64().unwrap(), vec![0, 0]); - assert_eq!(base64::decode(x).unwrap(), vec![0, 0]); + assert!(base64::decode(x).is_err()); let x = b"AAA"; assert_eq!(BASE64.decode(x).err().unwrap(), DecodeError { position: 0, kind: Length }); assert_eq!(x.from_base64().unwrap(), vec![0, 0]); diff --git a/lib/macro/Cargo.toml b/lib/macro/Cargo.toml index ff38c20..7919910 100644 --- a/lib/macro/Cargo.toml +++ b/lib/macro/Cargo.toml @@ -22,4 +22,4 @@ stable = ["data-encoding-macro-internal/stable", "proc-macro-hack"] [dependencies] data-encoding = { version = "2.1", path = ".." } data-encoding-macro-internal = { version = "0.1.6", path = "internal" } -proc-macro-hack = { version = "0.4", optional = true } +proc-macro-hack = { version = "0.5", optional = true } diff --git a/lib/macro/internal/Cargo.toml b/lib/macro/internal/Cargo.toml index f841221..7b7db6e 100644 --- a/lib/macro/internal/Cargo.toml +++ b/lib/macro/internal/Cargo.toml @@ -17,5 +17,5 @@ stable = ["proc-macro-hack"] [dependencies] data-encoding = { version = "2.1", path = "../.." } -proc-macro-hack = { version = "0.4.0", optional = true } -syn = "0.11.11" +proc-macro-hack = { version = "0.5", optional = true } +syn = "0.15" diff --git a/lib/macro/internal/src/lib.rs b/lib/macro/internal/src/lib.rs index 3559481..f3bb939 100644 --- a/lib/macro/internal/src/lib.rs +++ b/lib/macro/internal/src/lib.rs @@ -11,40 +11,26 @@ extern crate proc_macro; #[cfg(feature = "stable")] -#[macro_use] extern crate proc_macro_hack; extern crate syn; extern crate data_encoding; -#[cfg(not(feature = "stable"))] use proc_macro::token_stream::IntoIter; -#[cfg(not(feature = "stable"))] use proc_macro::{TokenStream, TokenTree}; -use std::collections::HashMap; #[cfg(feature = "stable")] -use syn::parse::IResult; -#[cfg(feature = "stable")] -use syn::{Lit, Token, TokenTree}; +use proc_macro_hack::proc_macro_hack; +use std::collections::HashMap; use data_encoding::{BitOrder, Encoding, Specification, Translate, Wrap}; -#[cfg(not(feature = "stable"))] fn parse_op(tokens: &mut IntoIter, op: char, key: &str) { match tokens.next() { Some(TokenTree::Punct(ref x)) if x.as_char() == op => (), _ => panic!("expected {:?} after {}", op, key), } } -#[cfg(feature = "stable")] -fn parse_op<'a>(input: &'a str, op: Token, key: &str) -> &'a str { - match syn::parse::tt(input) { - IResult::Done(rest, TokenTree::Token(ref x)) if x == &op => rest, - _ => panic!("expected {:?} after {}", op, key), - } -} -#[cfg(not(feature = "stable"))] fn parse_map(mut tokens: IntoIter) -> HashMap { let mut map = HashMap::new(); while let Some(key) = tokens.next() { @@ -62,54 +48,18 @@ fn parse_map(mut tokens: IntoIter) -> HashMap { } map } -#[cfg(feature = "stable")] -fn parse_map(mut input: &str) -> HashMap { - let mut map = HashMap::new(); - while let IResult::Done(rest, key) = syn::parse::tt(input) { - input = rest; - let key = match key { - TokenTree::Token(Token::Ident(key)) => key, - _ => panic!("expected key got {:?}", key), - }; - input = parse_op(input, Token::Colon, key.as_ref()); - let value = match syn::parse::tt(input) { - IResult::Done(rest, TokenTree::Token(value)) => { - input = rest; - value - } - _ => panic!("expected value for {}", key), - }; - input = parse_op(input, Token::Comma, key.as_ref()); - let _ = map.insert(key.as_ref().to_string(), value); - } - map -} -#[cfg(not(feature = "stable"))] fn get_string(map: &mut HashMap, key: &str) -> String { let node = match map.remove(key) { None => return String::new(), Some(node) => node, }; - let literal = match node { - TokenTree::Literal(literal) => literal, - _ => panic!("expected literal for {}", key), - }; - match syn::parse::string(&literal.to_string()) { - syn::parse::IResult::Done(_, result) => result.value, + match syn::parse::(node.into()) { + Ok(result) => result.value(), _ => panic!("expected string for {}", key), } } -#[cfg(feature = "stable")] -fn get_string(map: &mut HashMap, key: &str) -> String { - match map.remove(key) { - None => String::new(), - Some(Token::Literal(Lit::Str(value, _))) => value, - Some(_) => panic!("expected string literal for {}", key), - } -} -#[cfg(not(feature = "stable"))] fn get_usize(map: &mut HashMap, key: &str) -> usize { let node = match map.remove(key) { None => return 0, @@ -124,60 +74,32 @@ fn get_usize(map: &mut HashMap, key: &str) -> usize { Err(error) => panic!("expected usize for {}: {}", key, error), } } -#[cfg(feature = "stable")] -fn get_usize(map: &mut HashMap, key: &str) -> usize { - match map.remove(key) { - None => 0, - Some(Token::Literal(Lit::Int(value, _))) => value as usize, - Some(_) => panic!("expected usize for {}", key), - } -} -#[cfg(not(feature = "stable"))] fn get_padding(map: &mut HashMap) -> Option { let node = match map.remove("padding") { None => return None, Some(node) => node, }; - let literal = match node { - TokenTree::Ident(ref ident) if format!("{}", ident) == "None" => return None, - TokenTree::Literal(literal) => literal, - _ => panic!("expected literal for padding"), - }; - Some(syn::parse::character(&literal.to_string()).expect("expected char for padding")) -} -#[cfg(feature = "stable")] -fn get_padding(map: &mut HashMap) -> Option { - match map.remove("padding") { - None => None, - Some(Token::Ident(ref ident)) if ident.as_ref() == "None" => None, - Some(Token::Literal(Lit::Char(value))) => Some(value), - Some(_) => panic!("expected char for padding"), + if let Ok(result) = syn::parse::(node.clone().into()) { + return Some(result.value()); + } + match syn::parse::(node.into()) { + Ok(ref result) if result.to_string() == "None" => None, + _ => panic!("expected None or char for padding"), } } -#[cfg(not(feature = "stable"))] fn get_bool(map: &mut HashMap, key: &str) -> Option { let node = match map.remove(key) { None => return None, Some(node) => node, }; - let ident = match node { - TokenTree::Ident(ident) => format!("{}", ident), - _ => panic!("expected literal for padding"), - }; - Some(syn::parse::boolean(&ident).expect("expected bool for padding")) -} -#[cfg(feature = "stable")] -fn get_bool(map: &mut HashMap, key: &str) -> Option { - match map.remove(key) { - None => None, - Some(Token::Literal(Lit::Bool(value))) => Some(value), - Some(_) => panic!("expected bool for {}", key), + match syn::parse::(node.into()) { + Ok(result) => Some(result.value), + _ => panic!("expected bool for padding"), } } -#[cfg(not(feature = "stable"))] fn get_bit_order(map: &mut HashMap) -> BitOrder { let node = match map.remove("bit_order") { None => return BitOrder::MostSignificantFirst, @@ -195,17 +117,6 @@ fn get_bit_order(map: &mut HashMap) -> BitOrder { _ => panic!("expected {} or {} for bit_order", msb, lsb), } } -#[cfg(feature = "stable")] -fn get_bit_order(map: &mut HashMap) -> BitOrder { - let msb = "MostSignificantFirst"; - let lsb = "LeastSignificantFirst"; - match map.remove("bit_order") { - None => BitOrder::MostSignificantFirst, - Some(Token::Ident(ref ident)) if ident.as_ref() == msb => BitOrder::MostSignificantFirst, - Some(Token::Ident(ref ident)) if ident.as_ref() == lsb => BitOrder::LeastSignificantFirst, - Some(_) => panic!("expected {} or {} for bit_order", msb, lsb), - } -} fn check_present(hash_map: &HashMap, key: &str) { if !hash_map.contains_key(key) { @@ -213,7 +124,6 @@ fn check_present(hash_map: &HashMap, key: &str) { } } -#[cfg(not(feature = "stable"))] fn get_encoding(mut hash_map: &mut HashMap) -> Encoding { check_present(&hash_map, "symbols"); let spec = Specification { @@ -233,26 +143,6 @@ fn get_encoding(mut hash_map: &mut HashMap) -> Encoding { }; spec.encoding().unwrap() } -#[cfg(feature = "stable")] -fn get_encoding(mut hash_map: &mut HashMap) -> Encoding { - check_present(&hash_map, "symbols"); - let spec = Specification { - symbols: get_string(&mut hash_map, "symbols"), - bit_order: get_bit_order(&mut hash_map), - check_trailing_bits: get_bool(&mut hash_map, "check_trailing_bits").unwrap_or(true), - padding: get_padding(&mut hash_map), - ignore: get_string(&mut hash_map, "ignore"), - wrap: Wrap { - width: get_usize(&mut hash_map, "wrap_width"), - separator: get_string(&mut hash_map, "wrap_separator"), - }, - translate: Translate { - from: get_string(&mut hash_map, "translate_from"), - to: get_string(&mut hash_map, "translate_to"), - }, - }; - spec.encoding().unwrap() -} fn check_empty(hash_map: HashMap) { if !hash_map.is_empty() { @@ -260,8 +150,8 @@ fn check_empty(hash_map: HashMap) { } } -#[cfg(not(feature = "stable"))] -#[proc_macro] +#[cfg_attr(feature = "stable", proc_macro_hack)] +#[cfg_attr(not(feature = "stable"), proc_macro)] #[doc(hidden)] pub fn internal_new_encoding(input: TokenStream) -> TokenStream { let mut hash_map = parse_map(input.into_iter()); @@ -269,16 +159,6 @@ pub fn internal_new_encoding(input: TokenStream) -> TokenStream { check_empty(hash_map); format!("{:?}", encoding.internal_implementation()).parse().unwrap() } -#[cfg(feature = "stable")] -proc_macro_expr_impl! { - #[doc(hidden)] - pub fn internal_new_encoding_impl(input: &str) -> String { - let mut hash_map = parse_map(input); - let encoding = get_encoding(&mut hash_map); - check_empty(hash_map); - format!("{:?}", encoding.internal_implementation()) - } -} #[cfg(not(feature = "stable"))] #[proc_macro] @@ -294,8 +174,9 @@ pub fn internal_decode_array(input: TokenStream) -> TokenStream { let output = encoding.decode(input.as_bytes()).unwrap(); format!("{}: [u8; {}] = {:?};", name, output.len(), output).parse().unwrap() } -#[cfg(not(feature = "stable"))] -#[proc_macro] + +#[cfg_attr(feature = "stable", proc_macro_hack)] +#[cfg_attr(not(feature = "stable"), proc_macro)] #[doc(hidden)] pub fn internal_decode_slice(input: TokenStream) -> TokenStream { let mut hash_map = parse_map(input.into_iter()); @@ -305,15 +186,3 @@ pub fn internal_decode_slice(input: TokenStream) -> TokenStream { check_empty(hash_map); format!("{:?}", encoding.decode(input.as_bytes()).unwrap()).parse().unwrap() } -#[cfg(feature = "stable")] -proc_macro_expr_impl! { - #[doc(hidden)] - pub fn internal_decode_slice_impl(input: &str) -> String { - let mut hash_map = parse_map(input); - let encoding = get_encoding(&mut hash_map); - check_present(&hash_map, "input"); - let input = get_string(&mut hash_map, "input"); - check_empty(hash_map); - format!("{:?}", encoding.decode(input.as_bytes()).unwrap()) - } -} diff --git a/lib/macro/src/lib.rs b/lib/macro/src/lib.rs index 0cf559a..fafe8c6 100644 --- a/lib/macro/src/lib.rs +++ b/lib/macro/src/lib.rs @@ -72,27 +72,27 @@ #![warn(unused_results)] #[cfg(feature = "stable")] -#[macro_use] extern crate proc_macro_hack; extern crate data_encoding; -#[cfg_attr(feature = "stable", allow(unused_imports))] -#[cfg_attr(feature = "stable", macro_use)] extern crate data_encoding_macro_internal; +#[cfg(feature = "stable")] +use proc_macro_hack::proc_macro_hack; + +#[cfg(not(feature = "stable"))] #[doc(hidden)] pub use data_encoding_macro_internal::*; #[cfg(feature = "stable")] -proc_macro_expr_decl! { - #[doc(hidden)] - internal_new_encoding! => internal_new_encoding_impl -} +#[proc_macro_hack] +#[doc(hidden)] +pub use data_encoding_macro_internal::internal_new_encoding; + #[cfg(feature = "stable")] -proc_macro_expr_decl! { - #[doc(hidden)] - internal_decode_slice! => internal_decode_slice_impl -} +#[proc_macro_hack] +#[doc(hidden)] +pub use data_encoding_macro_internal::internal_decode_slice; /// Defines a compile-time byte array by decoding a string literal /// diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 2d656d1..65d3bf9 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -115,9 +115,9 @@ //! //! | Input | `data-encoding` | `rustc` | `base64` | GNU `base64` | //! | ---------- | --------------- | -------- | -------- | ------------- | -//! | `AAB=` | `Trailing(2)` | `[0, 0]` | `[0, 0]` | `\x00\x00` | +//! | `AAB=` | `Trailing(2)` | `[0, 0]` | `Err(2)` | `\x00\x00` | //! | `AA\nB=` | `Length(4)` | `[0, 0]` | `Length` | `\x00\x00` | -//! | `AAB` | `Length(0)` | `[0, 0]` | `[0, 0]` | Invalid input | +//! | `AAB` | `Length(0)` | `[0, 0]` | `Err(2)` | Invalid input | //! | `A\rA\nB=` | `Length(4)` | `[0, 0]` | `Err(1)` | Invalid input | //! | `-_\r\n` | `Symbol(0)` | `[251]` | `Err(0)` | Invalid input | //! | `AA==AA==` | `[0, 0]` | `Err` | `Err(2)` | `\x00\x00` | diff --git a/travis.sh b/travis.sh index cdb28f8..edcc382 100755 --- a/travis.sh +++ b/travis.sh @@ -44,6 +44,12 @@ git clean -fxd info "Benchmark binary" ./bench.sh ) +( info "Ensure cargo-outdated is installed" + which cargo-outdated >/dev/null || cargo install cargo-outdated + + info "Test dependencies" + cargo outdated -w -R --exit-code=1 +) ( git clean -fxd