Skip to content

Commit c825748

Browse files
bors[bot]ihciah
andauthored
Merge #11549
11549: feat: support concat_bytes r=jonas-schievink a=ihciah Support `concat_bytes`. Solve #11544. Co-authored-by: ihciah <[email protected]>
2 parents 1d5df5e + 494fab2 commit c825748

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs

+18
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,24 @@ fn main() { "foor0bar\nfalse"; }
313313
);
314314
}
315315

316+
#[test]
317+
fn test_concat_bytes_expand() {
318+
check(
319+
r##"
320+
#[rustc_builtin_macro]
321+
macro_rules! concat_bytes {}
322+
323+
fn main() { concat_bytes!(b'A', b"BC", [68, b'E', 70]); }
324+
"##,
325+
expect![[r##"
326+
#[rustc_builtin_macro]
327+
macro_rules! concat_bytes {}
328+
329+
fn main() { [b'A', 66, 67, 68, b'E', 70]; }
330+
"##]],
331+
);
332+
}
333+
316334
#[test]
317335
fn test_concat_with_captured_expr() {
318336
check(

crates/hir_expand/src/builtin_fn_macro.rs

+75
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ register_builtin! {
121121
(compile_error, CompileError) => compile_error_expand,
122122
(concat, Concat) => concat_expand,
123123
(concat_idents, ConcatIdents) => concat_idents_expand,
124+
(concat_bytes, ConcatBytes) => concat_bytes_expand,
124125
(include, Include) => include_expand,
125126
(include_bytes, IncludeBytes) => include_bytes_expand,
126127
(include_str, IncludeStr) => include_str_expand,
@@ -359,6 +360,12 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
359360
token.value().map(|it| it.into_owned())
360361
}
361362

363+
fn unquote_byte_string(lit: &tt::Literal) -> Option<Vec<u8>> {
364+
let lit = ast::make::tokens::literal(&lit.to_string());
365+
let token = ast::ByteString::cast(lit)?;
366+
token.value().map(|it| it.into_owned())
367+
}
368+
362369
fn compile_error_expand(
363370
_db: &dyn AstDatabase,
364371
_id: MacroCallId,
@@ -422,6 +429,74 @@ fn concat_expand(
422429
ExpandResult { value: ExpandedEager::new(quote!(#text)), err }
423430
}
424431

432+
fn concat_bytes_expand(
433+
_db: &dyn AstDatabase,
434+
_arg_id: MacroCallId,
435+
tt: &tt::Subtree,
436+
) -> ExpandResult<ExpandedEager> {
437+
let mut bytes = Vec::new();
438+
let mut err = None;
439+
for (i, t) in tt.token_trees.iter().enumerate() {
440+
match t {
441+
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
442+
let token = ast::make::tokens::literal(&lit.to_string());
443+
match token.kind() {
444+
syntax::SyntaxKind::BYTE => bytes.push(token.text().to_string()),
445+
syntax::SyntaxKind::BYTE_STRING => {
446+
let components = unquote_byte_string(lit).unwrap_or_else(|| Vec::new());
447+
components.into_iter().for_each(|x| bytes.push(x.to_string()));
448+
}
449+
_ => {
450+
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
451+
break;
452+
}
453+
}
454+
}
455+
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
456+
tt::TokenTree::Subtree(tree)
457+
if tree.delimiter_kind() == Some(tt::DelimiterKind::Bracket) =>
458+
{
459+
if let Err(e) = concat_bytes_expand_subtree(tree, &mut bytes) {
460+
err.get_or_insert(e);
461+
break;
462+
}
463+
}
464+
_ => {
465+
err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
466+
break;
467+
}
468+
}
469+
}
470+
let ident = tt::Ident { text: bytes.join(", ").into(), id: tt::TokenId::unspecified() };
471+
ExpandResult { value: ExpandedEager::new(quote!([#ident])), err }
472+
}
473+
474+
fn concat_bytes_expand_subtree(
475+
tree: &tt::Subtree,
476+
bytes: &mut Vec<String>,
477+
) -> Result<(), ExpandError> {
478+
for (ti, tt) in tree.token_trees.iter().enumerate() {
479+
match tt {
480+
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
481+
let lit = ast::make::tokens::literal(&lit.to_string());
482+
match lit.kind() {
483+
syntax::SyntaxKind::BYTE | syntax::SyntaxKind::INT_NUMBER => {
484+
bytes.push(lit.text().to_string())
485+
}
486+
_ => {
487+
return Err(mbe::ExpandError::UnexpectedToken.into());
488+
}
489+
}
490+
}
491+
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
492+
_ => {
493+
return Err(mbe::ExpandError::UnexpectedToken.into());
494+
}
495+
}
496+
}
497+
Ok(())
498+
}
499+
425500
fn concat_idents_expand(
426501
_db: &dyn AstDatabase,
427502
_arg_id: MacroCallId,

crates/hir_expand/src/name.rs

+1
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ pub mod known {
233233
column,
234234
compile_error,
235235
concat_idents,
236+
concat_bytes,
236237
concat,
237238
const_format_args,
238239
core_panic,

0 commit comments

Comments
 (0)