// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. /* The compiler code necessary to support the bytes! extension. */ use ast; use codemap::Span; use ext::base::*; use ext::base; use ext::build::AstBuilder; use std::char; use std::vec_ng::Vec; pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> base::MacResult { // Gather all argument expressions let exprs = match get_exprs_from_tts(cx, sp, tts) { None => return MacResult::dummy_expr(sp), Some(e) => e, }; let mut bytes = Vec::new(); for expr in exprs.iter() { match expr.node { // expression is a literal ast::ExprLit(lit) => match lit.node { // string literal, push each byte to vector expression ast::LitStr(ref s, _) => { for byte in s.get().bytes() { bytes.push(cx.expr_u8(expr.span, byte)); } } // u8 literal, push to vector expression ast::LitUint(v, ast::TyU8) => { if v > 0xFF { cx.span_err(expr.span, "too large u8 literal in bytes!") } else { bytes.push(cx.expr_u8(expr.span, v as u8)); } } // integer literal, push to vector expression ast::LitIntUnsuffixed(v) => { if v > 0xFF { cx.span_err(expr.span, "too large integer literal in bytes!") } else if v < 0 { cx.span_err(expr.span, "negative integer literal in bytes!") } else { bytes.push(cx.expr_u8(expr.span, v as u8)); } } // char literal, push to vector expression ast::LitChar(v) => { if char::from_u32(v).unwrap().is_ascii() { bytes.push(cx.expr_u8(expr.span, v as u8)); } else { cx.span_err(expr.span, "non-ascii char literal in bytes!") } } _ => cx.span_err(expr.span, "unsupported literal in bytes!") }, _ => cx.span_err(expr.span, "non-literal in bytes!") } } let e = cx.expr_vec_slice(sp, bytes); MRExpr(e) }