Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi-preview1-component-adapter/byte-array-literals/src/lib.rs
2459 views
1
extern crate proc_macro;
2
3
use proc_macro::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree};
4
5
/// Expand a `str` literal into a byte array.
6
#[proc_macro]
7
pub fn str(input: TokenStream) -> TokenStream {
8
let rv = convert_str(input);
9
10
vec![TokenTree::Group(Group::new(
11
Delimiter::Bracket,
12
rv.into_iter().collect(),
13
))]
14
.into_iter()
15
.collect()
16
}
17
18
/// The same as `str` but appends a `'\n'`.
19
#[proc_macro]
20
pub fn str_nl(input: TokenStream) -> TokenStream {
21
let mut rv = convert_str(input);
22
23
rv.push(TokenTree::Literal(Literal::u8_suffixed(b'\n')));
24
25
vec![TokenTree::Group(Group::new(
26
Delimiter::Bracket,
27
rv.into_iter().collect(),
28
))]
29
.into_iter()
30
.collect()
31
}
32
33
fn convert_str(input: TokenStream) -> Vec<TokenTree> {
34
let mut it = input.into_iter();
35
36
let mut tokens = Vec::new();
37
match it.next() {
38
Some(TokenTree::Literal(l)) => {
39
for b in to_string(l).into_bytes() {
40
tokens.push(TokenTree::Literal(Literal::u8_suffixed(b)));
41
tokens.push(TokenTree::Punct(Punct::new(',', Spacing::Alone)));
42
}
43
}
44
_ => panic!(),
45
}
46
47
assert!(it.next().is_none());
48
tokens
49
}
50
51
fn to_string(lit: Literal) -> String {
52
let formatted = lit.to_string();
53
54
let mut it = formatted.chars();
55
assert_eq!(it.next(), Some('"'));
56
57
let mut rv = String::new();
58
loop {
59
match it.next() {
60
Some('"') => match it.next() {
61
Some(_) => panic!(),
62
None => break,
63
},
64
Some('\\') => match it.next() {
65
Some('x') => {
66
let hi = it.next().unwrap().to_digit(16).unwrap();
67
let lo = it.next().unwrap().to_digit(16).unwrap();
68
let v = (hi << 16) | lo;
69
rv.push(v as u8 as char);
70
}
71
Some('u') => {
72
assert_eq!(it.next(), Some('{'));
73
let mut c = it.next().unwrap();
74
let mut ch = 0;
75
while let Some(v) = c.to_digit(16) {
76
ch *= 16;
77
ch |= v;
78
c = it.next().unwrap();
79
}
80
assert_eq!(c, '}');
81
rv.push(::std::char::from_u32(ch).unwrap());
82
}
83
Some('0') => rv.push('\0'),
84
Some('\\') => rv.push('\\'),
85
Some('\"') => rv.push('\"'),
86
Some('r') => rv.push('\r'),
87
Some('n') => rv.push('\n'),
88
Some('t') => rv.push('\t'),
89
Some(_) => panic!(),
90
None => panic!(),
91
},
92
Some(c) => rv.push(c),
93
None => panic!(),
94
}
95
}
96
97
rv
98
}
99
100