Skip to content

Commit 1f408cc

Browse files
committed
Support byte string keys in phf_macros (fixes rust-phf#76)
Because of rust-lang/rust#31260, a cast must be inserted explicitly instead of letting rustc implicitly coercing the type.
1 parent ae5ee38 commit 1f408cc

File tree

2 files changed

+37
-24
lines changed

2 files changed

+37
-24
lines changed

phf_macros/src/lib.rs

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ extern crate phf_generator;
4242

4343
use std::collections::HashMap;
4444
use std::collections::hash_map::Entry::{Occupied, Vacant};
45-
use syntax::ast::{self, TokenTree, Expr, ExprLit, ExprVec};
45+
use syntax::ast::{self, Expr, ExprLit, ExprVec, MutImmutable, TokenTree, TyVec};
4646
use syntax::codemap::{Span, Spanned};
4747
use syntax::ext::base::{DummyResult, ExtCtxt, MacResult};
48+
use syntax::ext::build::AstBuilder;
4849
use syntax::fold::Folder;
4950
use syntax::parse;
5051
use syntax::parse::token::{InternedString, Comma, Eof, FatArrow};
5152
use syntax::print::pprust;
53+
use syntax::ptr::P;
5254
use rustc_plugin::Registry;
5355
use phf_generator::HashState;
5456
use std::env;
@@ -162,9 +164,9 @@ fn parse_map(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
162164
let mut bad = false;
163165
while parser.token != Eof {
164166
let key = cx.expander().fold_expr(parser.parse_expr().unwrap());
165-
let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
167+
let (key_contents, key) = parse_key(cx, key.clone()).unwrap_or_else(|| {
166168
bad = true;
167-
Key::Str(InternedString::new(""))
169+
(Key::Str(InternedString::new("")), key)
168170
});
169171

170172
if !parser.eat(&FatArrow) {
@@ -201,9 +203,9 @@ fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
201203
let mut bad = false;
202204
while parser.token != Eof {
203205
let key = cx.expander().fold_expr(parser.parse_expr().unwrap());
204-
let key_contents = parse_key(cx, &*key).unwrap_or_else(|| {
206+
let (key_contents, key) = parse_key(cx, key.clone()).unwrap_or_else(|| {
205207
bad = true;
206-
Key::Str(InternedString::new(""))
208+
(Key::Str(InternedString::new("")), key)
207209
});
208210

209211
entries.push(Entry {
@@ -225,34 +227,40 @@ fn parse_set(cx: &mut ExtCtxt, tts: &[TokenTree]) -> Option<Vec<Entry>> {
225227
Some(entries)
226228
}
227229

228-
fn parse_key(cx: &mut ExtCtxt, e: &Expr) -> Option<Key> {
230+
fn parse_key(cx: &mut ExtCtxt, e: P<Expr>) -> Option<(Key, P<Expr>)> {
229231
match e.node {
230232
ExprLit(ref lit) => {
231233
match lit.node {
232-
ast::LitStr(ref s, _) => Some(Key::Str(s.clone())),
233-
ast::LitByteStr(ref b) => Some(Key::Binary(b.clone())),
234-
ast::LitByte(b) => Some(Key::U8(b)),
235-
ast::LitChar(c) => Some(Key::Char(c)),
236-
ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Plus)) => Some(Key::I8(i as i8)),
234+
ast::LitStr(ref s, _) => Some((Key::Str(s.clone()), e.clone())),
235+
ast::LitByteStr(ref b) => {
236+
let u8_type = cx.ty_path(cx.path_ident(e.span, cx.ident_of("u8")));
237+
let array_type = cx.ty(e.span, TyVec(u8_type));
238+
let slice_type = cx.ty_rptr(e.span, array_type, None, MutImmutable);
239+
let key = cx.expr_cast(e.span, e.clone(), slice_type);
240+
Some((Key::Binary(b.clone()), key))
241+
},
242+
ast::LitByte(b) => Some((Key::U8(b), e.clone())),
243+
ast::LitChar(c) => Some((Key::Char(c), e.clone())),
244+
ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Plus)) => Some((Key::I8(i as i8), e.clone())),
237245
ast::LitInt(i, ast::SignedIntLit(ast::TyI8, ast::Minus)) =>
238-
Some(Key::I8(-(i as i8))),
246+
Some((Key::I8(-(i as i8)), e.clone())),
239247
ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Plus)) =>
240-
Some(Key::I16(i as i16)),
248+
Some((Key::I16(i as i16), e.clone())),
241249
ast::LitInt(i, ast::SignedIntLit(ast::TyI16, ast::Minus)) =>
242-
Some(Key::I16(-(i as i16))),
250+
Some((Key::I16(-(i as i16)), e.clone())),
243251
ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Plus)) =>
244-
Some(Key::I32(i as i32)),
252+
Some((Key::I32(i as i32), e.clone())),
245253
ast::LitInt(i, ast::SignedIntLit(ast::TyI32, ast::Minus)) =>
246-
Some(Key::I32(-(i as i32))),
254+
Some((Key::I32(-(i as i32)), e.clone())),
247255
ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Plus)) =>
248-
Some(Key::I64(i as i64)),
256+
Some((Key::I64(i as i64), e.clone())),
249257
ast::LitInt(i, ast::SignedIntLit(ast::TyI64, ast::Minus)) =>
250-
Some(Key::I64(-(i as i64))),
251-
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU8)) => Some(Key::U8(i as u8)),
252-
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU16)) => Some(Key::U16(i as u16)),
253-
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU32)) => Some(Key::U32(i as u32)),
254-
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU64)) => Some(Key::U64(i as u64)),
255-
ast::LitBool(b) => Some(Key::Bool(b)),
258+
Some((Key::I64(-(i as i64)), e.clone())),
259+
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU8)) => Some((Key::U8(i as u8), e.clone())),
260+
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU16)) => Some((Key::U16(i as u16), e.clone())),
261+
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU32)) => Some((Key::U32(i as u32), e.clone())),
262+
ast::LitInt(i, ast::UnsignedIntLit(ast::TyU64)) => Some((Key::U64(i as u64), e.clone())),
263+
ast::LitBool(b) => Some((Key::Bool(b), e.clone())),
256264
_ => {
257265
cx.span_err(e.span, "unsupported literal type");
258266
None
@@ -271,7 +279,7 @@ fn parse_key(cx: &mut ExtCtxt, e: &Expr) -> Option<Key> {
271279
None
272280
}).collect();
273281
if bytes.iter().all(|x| x.is_some()) {
274-
Some(Key::Binary(std::rc::Rc::new(bytes.iter().map(|x| x.unwrap()).collect())))
282+
Some((Key::Binary(std::rc::Rc::new(bytes.iter().map(|x| x.unwrap()).collect())), e.clone()))
275283
} else {
276284
cx.span_err(e.span,
277285
"not all elements of an expected u8 array literal were u8 literals");

phf_macros/tests/test.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ mod map {
1717
"foo" => 10
1818
);
1919

20+
#[allow(dead_code)]
21+
static BYTE_STRING_KEY: phf::Map<&'static [u8], &'static str> = phf_map!(
22+
b"camembert" => "delicious",
23+
);
24+
2025
#[test]
2126
fn test_two() {
2227
static MAP: phf::Map<&'static str, isize> = phf_map!(

0 commit comments

Comments
 (0)