Merge #11549
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:
commit
c8257488c1
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user