Skip to content

Commit

Permalink
Fixed-size byte string literals (RFC 339)
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Mar 17, 2015
1 parent bfac337 commit 1e9bef9
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 43 deletions.
9 changes: 1 addition & 8 deletions src/librustc_trans/trans/consts.rs
Expand Up @@ -75,14 +75,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
ast::LitBool(b) => C_bool(cx, b),
ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
ast::LitBinary(ref data) => {
let g = addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id);
let base = ptrcast(g, Type::i8p(cx));
let prev_const = cx.const_unsized().borrow_mut()
.insert(base, g);
assert!(prev_const.is_none() || prev_const == Some(g));
assert_eq!(abi::FAT_PTR_ADDR, 0);
assert_eq!(abi::FAT_PTR_EXTRA, 1);
C_struct(cx, &[base, C_uint(cx, data.len())], false)
addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id)
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -2505,10 +2505,11 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,

match lit.node {
ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
ast::LitBinary(..) => {
ty::mk_slice(tcx,
tcx.mk_region(ty::ReStatic),
ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
ast::LitBinary(ref v) => {
ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
mutbl: ast::MutImmutable,
})
}
ast::LitByte(_) => tcx.types.u8,
ast::LitChar(_) => tcx.types.char,
Expand Down
17 changes: 17 additions & 0 deletions src/libstd/ffi/c_str.rs
Expand Up @@ -451,6 +451,23 @@ impl IntoBytes for Vec<u8> {
fn into_bytes(self) -> Vec<u8> { self }
}

macro_rules! array_impls {
($($N: expr)+) => {
$(
impl<'a> IntoBytes for &'a [u8; $N] {
fn into_bytes(self) -> Vec<u8> { self.to_vec() }
}
)+
}
}

array_impls! {
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}

#[cfg(test)]
mod tests {
use prelude::v1::*;
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/io/buffered.rs
Expand Up @@ -622,7 +622,7 @@ mod tests {

#[test]
fn test_read_line() {
let in_buf = b"a\nb\nc";
let in_buf: &[u8] = b"a\nb\nc";
let mut reader = BufReader::with_capacity(2, in_buf);
let mut s = String::new();
reader.read_line(&mut s).unwrap();
Expand All @@ -640,7 +640,7 @@ mod tests {

#[test]
fn test_lines() {
let in_buf = b"a\nb\nc";
let in_buf: &[u8] = b"a\nb\nc";
let reader = BufReader::with_capacity(2, in_buf);
let mut it = reader.lines();
assert_eq!(it.next(), Some(Ok("a".to_string())));
Expand Down
17 changes: 17 additions & 0 deletions src/libstd/io/cursor.rs
Expand Up @@ -129,6 +129,23 @@ impl<'a> BufRead for Cursor<&'a mut [u8]> { buffer!(); }
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> BufRead for Cursor<Vec<u8>> { buffer!(); }

macro_rules! array_impls {
($($N: expr)+) => {
$(
impl<'a> io::Seek for Cursor<&'a [u8; $N]> { seek!(); }
impl<'a> Read for Cursor<&'a [u8; $N]> { read!(); }
impl<'a> BufRead for Cursor<&'a [u8; $N]> { buffer!(); }
)+
}
}

array_impls! {
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for Cursor<&'a mut [u8]> {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/old_io/util.rs
Expand Up @@ -445,7 +445,8 @@ mod test {

#[test]
fn limit_reader_buffer() {
let r = &mut b"0123456789\n0123456789\n";
let mut r: &[u8] = b"0123456789\n0123456789\n";
let r = &mut r;
{
let mut r = LimitReader::new(r.by_ref(), 3);
assert_eq!(r.read_line(), Ok("012".to_string()));
Expand Down
20 changes: 20 additions & 0 deletions src/libstd/old_path/mod.rs
Expand Up @@ -895,6 +895,26 @@ impl BytesContainer for [u8] {
}
}

macro_rules! array_impls {
($($N: expr)+) => {
$(
impl BytesContainer for [u8; $N] {
#[inline]
fn container_as_bytes(&self) -> &[u8] {
&self[..]
}
}
)+
}
}

array_impls! {
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}

impl BytesContainer for Vec<u8> {
#[inline]
fn container_as_bytes(&self) -> &[u8] {
Expand Down
30 changes: 15 additions & 15 deletions src/libstd/old_path/posix.rs
Expand Up @@ -632,9 +632,9 @@ mod tests {
);
}

t!(v: b"a/b/c", filename, Some(b"c"));
t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF"));
t!(v: b"a/b\xFF/c", filename, Some(b"c"));
t!(v: b"a/b/c", filename, Some(&b"c"[..]));
t!(v: b"a/b/c\xFF", filename, Some(&b"c\xFF"[..]));
t!(v: b"a/b\xFF/c", filename, Some(&b"c"[..]));
t!(s: "a/b/c", filename, Some("c"), opt);
t!(s: "/a/b/c", filename, Some("c"), opt);
t!(s: "a", filename, Some("a"), opt);
Expand All @@ -656,9 +656,9 @@ mod tests {
t!(s: "..", dirname, "..");
t!(s: "../..", dirname, "../..");

t!(v: b"hi/there.txt", filestem, Some(b"there"));
t!(v: b"hi/there\x80.txt", filestem, Some(b"there\x80"));
t!(v: b"hi/there.t\x80xt", filestem, Some(b"there"));
t!(v: b"hi/there.txt", filestem, Some(&b"there"[..]));
t!(v: b"hi/there\x80.txt", filestem, Some(&b"there\x80"[..]));
t!(v: b"hi/there.t\x80xt", filestem, Some(&b"there"[..]));
t!(s: "hi/there.txt", filestem, Some("there"), opt);
t!(s: "hi/there", filestem, Some("there"), opt);
t!(s: "there.txt", filestem, Some("there"), opt);
Expand All @@ -672,9 +672,9 @@ mod tests {
t!(s: "..", filestem, None, opt);
t!(s: "../..", filestem, None, opt);

t!(v: b"hi/there.txt", extension, Some(b"txt"));
t!(v: b"hi/there\x80.txt", extension, Some(b"txt"));
t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt"));
t!(v: b"hi/there.txt", extension, Some(&b"txt"[..]));
t!(v: b"hi/there\x80.txt", extension, Some(&b"txt"[..]));
t!(v: b"hi/there.t\x80xt", extension, Some(&b"t\x80xt"[..]));
t!(v: b"hi/there", extension, None);
t!(v: b"hi/there\x80", extension, None);
t!(s: "hi/there.txt", extension, Some("txt"), opt);
Expand Down Expand Up @@ -756,8 +756,8 @@ mod tests {
t!(s: "a/b/c", ["d", "/e"], "/e");
t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e");
t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e");
t!(v: b"a/b/c", [b"d", b"/e", b"f"], b"/e/f");
t!(v: b"a/b/c", [&b"d"[..], &b"e"[..]], b"a/b/c/d/e");
t!(v: b"a/b/c", [&b"d"[..], &b"/e"[..], &b"f"[..]], b"/e/f");
t!(v: b"a/b/c", [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e");
}

Expand Down Expand Up @@ -983,10 +983,10 @@ mod tests {
)
}

t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None);
t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None);
t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi",
Some(b"there"), Some(b"\xFF"));
t!(v: Path::new(b"a/b/c"), Some(&b"c"[..]), b"a/b", Some(&b"c"[..]), None);
t!(v: Path::new(b"a/b/\xFF"), Some(&b"\xFF"[..]), b"a/b", Some(&b"\xFF"[..]), None);
t!(v: Path::new(b"hi/there.\xFF"), Some(&b"there.\xFF"[..]), b"hi",
Some(&b"there"[..]), Some(&b"\xFF"[..]));
t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None);
t!(s: Path::new("."), None, Some("."), None, None);
t!(s: Path::new("/"), None, Some("/"), None, None);
Expand Down
12 changes: 6 additions & 6 deletions src/libstd/old_path/windows.rs
Expand Up @@ -1397,7 +1397,7 @@ mod tests {
)
}

t!(v: b"a\\b\\c", filename, Some(b"c"));
t!(v: b"a\\b\\c", filename, Some(&b"c"[..]));
t!(s: "a\\b\\c", filename_str, "c");
t!(s: "\\a\\b\\c", filename_str, "c");
t!(s: "a", filename_str, "a");
Expand Down Expand Up @@ -1461,7 +1461,7 @@ mod tests {
t!(s: "\\\\.\\foo", dirname_str, "\\\\.\\foo");
t!(s: "\\\\?\\a\\b\\", dirname_str, "\\\\?\\a");

t!(v: b"hi\\there.txt", filestem, Some(b"there"));
t!(v: b"hi\\there.txt", filestem, Some(&b"there"[..]));
t!(s: "hi\\there.txt", filestem_str, "there");
t!(s: "hi\\there", filestem_str, "there");
t!(s: "there.txt", filestem_str, "there");
Expand All @@ -1476,7 +1476,7 @@ mod tests {
t!(s: "..\\..", filestem_str, None, opt);
// filestem is based on filename, so we don't need the full set of prefix tests

t!(v: b"hi\\there.txt", extension, Some(b"txt"));
t!(v: b"hi\\there.txt", extension, Some(&b"txt"[..]));
t!(v: b"hi\\there", extension, None);
t!(s: "hi\\there.txt", extension_str, Some("txt"), opt);
t!(s: "hi\\there", extension_str, None, opt);
Expand Down Expand Up @@ -1603,8 +1603,8 @@ mod tests {
t!(s: "a\\b\\c", ["d", "\\e"], "\\e");
t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e");
t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e");
t!(v: b"a\\b\\c", [b"d", b"\\e", b"f"], b"\\e\\f");
t!(v: b"a\\b\\c", [&b"d"[..], &b"e"[..]], b"a\\b\\c\\d\\e");
t!(v: b"a\\b\\c", [&b"d"[..], &b"\\e"[..], &b"f"[..]], b"\\e\\f");
t!(v: b"a\\b\\c", [b"d".to_vec(), b"e".to_vec()],
b"a\\b\\c\\d\\e");
}
Expand Down Expand Up @@ -1898,7 +1898,7 @@ mod tests {
)
}

t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None);
t!(v: Path::new(b"a\\b\\c"), Some(&b"c"[..]), b"a\\b", Some(&b"c"[..]), None);
t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
t!(s: Path::new("."), None, Some("."), None, None);
t!(s: Path::new("\\"), None, Some("\\"), None, None);
Expand Down
22 changes: 15 additions & 7 deletions src/test/run-pass/byte-literals.rs
Expand Up @@ -13,9 +13,13 @@

static FOO: u8 = b'\xF0';
static BAR: &'static [u8] = b"a\xF0\t";
static BAR_FIXED: &'static [u8; 3] = b"a\xF0\t";
static BAZ: &'static [u8] = br"a\n";

pub fn main() {
let bar: &'static [u8] = b"a\xF0\t";
let bar_fixed: &'static [u8; 3] = b"a\xF0\t";

assert_eq!(b'a', 97u8);
assert_eq!(b'\n', 10u8);
assert_eq!(b'\r', 13u8);
Expand Down Expand Up @@ -44,19 +48,23 @@ pub fn main() {
b", expected);
let expected: &[_] = &[97u8, 240u8, 9u8];
assert_eq!(BAR, expected);
assert_eq!(BAR_FIXED, expected);
assert_eq!(bar, expected);
assert_eq!(bar_fixed, expected);

let val: &[_] = &[97u8, 10u8];
let val = &[97u8, 10u8];
match val {
b"a\n" => {},
_ => panic!(),
}

let buf = vec!(97u8, 98, 99, 100);
assert_eq!(match &buf[0..3] {
b"def" => 1_usize,
b"abc" => 2_usize,
_ => 3_usize
}, 2);
// FIXME: There are no DST coercions &[T; N] -> &[T] in patterns
// let buf = vec!(97u8, 98, 99, 100);
// assert_eq!(match &buf[0..3] {
// b"def" => 1_usize,
// b"abc" => 2_usize,
// _ => 3_usize
// }, 2);

let expected: &[_] = &[97u8, 92u8, 110u8];
assert_eq!(BAZ, expected);
Expand Down

0 comments on commit 1e9bef9

Please sign in to comment.