11549: feat: support concat_bytes r=jonas-schievink a=ihciah

Support `concat_bytes`.
Solve #11544.

Co-authored-by: ihciah <ihciah@gmail.com>
This commit is contained in:
bors[bot] 2022-02-25 13:34:18 +00:00 committed by GitHub
commit c8257488c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 94 additions and 0 deletions

View File

@ -313,6 +313,24 @@ fn main() { "foor0bar\nfalse"; }
); );
} }
#[test]
fn test_concat_bytes_expand() {
check(
r##"
#[rustc_builtin_macro]
macro_rules! concat_bytes {}
fn main() { concat_bytes!(b'A', b"BC", [68, b'E', 70]); }
"##,
expect![[r##"
#[rustc_builtin_macro]
macro_rules! concat_bytes {}
fn main() { [b'A', 66, 67, 68, b'E', 70]; }
"##]],
);
}
#[test] #[test]
fn test_concat_with_captured_expr() { fn test_concat_with_captured_expr() {
check( check(

View File

@ -121,6 +121,7 @@ register_builtin! {
(compile_error, CompileError) => compile_error_expand, (compile_error, CompileError) => compile_error_expand,
(concat, Concat) => concat_expand, (concat, Concat) => concat_expand,
(concat_idents, ConcatIdents) => concat_idents_expand, (concat_idents, ConcatIdents) => concat_idents_expand,
(concat_bytes, ConcatBytes) => concat_bytes_expand,
(include, Include) => include_expand, (include, Include) => include_expand,
(include_bytes, IncludeBytes) => include_bytes_expand, (include_bytes, IncludeBytes) => include_bytes_expand,
(include_str, IncludeStr) => include_str_expand, (include_str, IncludeStr) => include_str_expand,
@ -359,6 +360,12 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
token.value().map(|it| it.into_owned()) token.value().map(|it| it.into_owned())
} }
fn unquote_byte_string(lit: &tt::Literal) -> Option<Vec<u8>> {
let lit = ast::make::tokens::literal(&lit.to_string());
let token = ast::ByteString::cast(lit)?;
token.value().map(|it| it.into_owned())
}
fn compile_error_expand( fn compile_error_expand(
_db: &dyn AstDatabase, _db: &dyn AstDatabase,
_id: MacroCallId, _id: MacroCallId,
@ -422,6 +429,74 @@ fn concat_expand(
ExpandResult { value: ExpandedEager::new(quote!(#text)), err } ExpandResult { value: ExpandedEager::new(quote!(#text)), err }
} }
fn concat_bytes_expand(
_db: &dyn AstDatabase,
_arg_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<ExpandedEager> {
let mut bytes = Vec::new();
let mut err = None;
for (i, t) in tt.token_trees.iter().enumerate() {
match t {
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
let token = ast::make::tokens::literal(&lit.to_string());
match token.kind() {
syntax::SyntaxKind::BYTE => bytes.push(token.text().to_string()),
syntax::SyntaxKind::BYTE_STRING => {
let components = unquote_byte_string(lit).unwrap_or_else(|| Vec::new());
components.into_iter().for_each(|x| bytes.push(x.to_string()));
}
_ => {
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
break;
}
}
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
tt::TokenTree::Subtree(tree)
if tree.delimiter_kind() == Some(tt::DelimiterKind::Bracket) =>
{
if let Err(e) = concat_bytes_expand_subtree(tree, &mut bytes) {
err.get_or_insert(e);
break;
}
}
_ => {
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
break;
}
}
}
let ident = tt::Ident { text: bytes.join(", ").into(), id: tt::TokenId::unspecified() };
ExpandResult { value: ExpandedEager::new(quote!([#ident])), err }
}
fn concat_bytes_expand_subtree(
tree: &tt::Subtree,
bytes: &mut Vec<String>,
) -> Result<(), ExpandError> {
for (ti, tt) in tree.token_trees.iter().enumerate() {
match tt {
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
let lit = ast::make::tokens::literal(&lit.to_string());
match lit.kind() {
syntax::SyntaxKind::BYTE | syntax::SyntaxKind::INT_NUMBER => {
bytes.push(lit.text().to_string())
}
_ => {
return Err(mbe::ExpandError::UnexpectedToken.into());
}
}
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
_ => {
return Err(mbe::ExpandError::UnexpectedToken.into());
}
}
}
Ok(())
}
fn concat_idents_expand( fn concat_idents_expand(
_db: &dyn AstDatabase, _db: &dyn AstDatabase,
_arg_id: MacroCallId, _arg_id: MacroCallId,

View File

@ -233,6 +233,7 @@ pub mod known {
column, column,
compile_error, compile_error,
concat_idents, concat_idents,
concat_bytes,
concat, concat,
const_format_args, const_format_args,
core_panic, core_panic,