1#[cfg(feature = "sysroot-abi")]
38use proc_macro_srv::TokenStream;
39
40use std::collections::VecDeque;
41
42use intern::Symbol;
43use rustc_hash::FxHashMap;
44use serde_derive::{Deserialize, Serialize};
45use span::{EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContext, TextRange};
46
47use crate::{
48 legacy_protocol::SpanId,
49 version::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA},
50};
51
52pub type SpanDataIndexMap =
53 indexmap::IndexSet<Span, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
54
55pub fn serialize_span_data_index_map(map: &SpanDataIndexMap) -> Vec<u32> {
56 map.iter()
57 .flat_map(|span| {
58 [
59 span.anchor.file_id.as_u32(),
60 span.anchor.ast_id.into_raw(),
61 span.range.start().into(),
62 span.range.end().into(),
63 span.ctx.into_u32(),
64 ]
65 })
66 .collect()
67}
68
69pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap {
70 debug_assert!(map.len().is_multiple_of(5));
71 map.chunks_exact(5)
72 .map(|span| {
73 let &[file_id, ast_id, start, end, e] = span else { unreachable!() };
74 Span {
75 anchor: SpanAnchor {
76 file_id: EditionedFileId::from_raw(file_id),
77 ast_id: ErasedFileAstId::from_raw(ast_id),
78 },
79 range: TextRange::new(start.into(), end.into()),
80 ctx: unsafe { SyntaxContext::from_u32(e) },
83 }
84 })
85 .collect()
86}
87
88#[derive(Serialize, Deserialize, Debug, Clone)]
89pub struct FlatTree {
90 subtree: Vec<u32>,
91 literal: Vec<u32>,
92 punct: Vec<u32>,
93 ident: Vec<u32>,
94 token_tree: Vec<u32>,
95 text: Vec<String>,
96}
97
98struct SubtreeRepr {
99 open: SpanId,
100 close: SpanId,
101 kind: tt::DelimiterKind,
102 tt: [u32; 2],
103}
104
105struct LiteralRepr {
106 id: SpanId,
107 text: u32,
108 suffix: u32,
109 kind: u16,
110}
111
112struct PunctRepr {
113 id: SpanId,
114 char: char,
115 spacing: tt::Spacing,
116}
117
118struct IdentRepr {
119 id: SpanId,
120 text: u32,
121 is_raw: bool,
122}
123
124impl FlatTree {
125 pub fn from_subtree(
126 subtree: tt::SubtreeView<'_, Span>,
127 version: u32,
128 span_data_table: &mut SpanDataIndexMap,
129 ) -> FlatTree {
130 let mut w = Writer::<Span, _> {
131 string_table: FxHashMap::default(),
132 work: VecDeque::new(),
133 span_data_table,
134
135 subtree: Vec::new(),
136 literal: Vec::new(),
137 punct: Vec::new(),
138 ident: Vec::new(),
139 token_tree: Vec::new(),
140 text: Vec::new(),
141 version,
142 };
143 w.write_subtree(subtree);
144
145 FlatTree {
146 subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
147 write_vec(w.subtree, SubtreeRepr::write_with_close_span)
148 } else {
149 write_vec(w.subtree, SubtreeRepr::write)
150 },
151 literal: if version >= EXTENDED_LEAF_DATA {
152 write_vec(w.literal, LiteralRepr::write_with_kind)
153 } else {
154 write_vec(w.literal, LiteralRepr::write)
155 },
156 punct: write_vec(w.punct, PunctRepr::write),
157 ident: if version >= EXTENDED_LEAF_DATA {
158 write_vec(w.ident, IdentRepr::write_with_rawness)
159 } else {
160 write_vec(w.ident, IdentRepr::write)
161 },
162 token_tree: w.token_tree,
163 text: w.text,
164 }
165 }
166
167 pub fn to_subtree_resolved(
168 self,
169 version: u32,
170 span_data_table: &SpanDataIndexMap,
171 ) -> tt::TopSubtree<Span> {
172 Reader::<Span> {
173 subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
174 read_vec(self.subtree, SubtreeRepr::read_with_close_span)
175 } else {
176 read_vec(self.subtree, SubtreeRepr::read)
177 },
178 literal: if version >= EXTENDED_LEAF_DATA {
179 read_vec(self.literal, LiteralRepr::read_with_kind)
180 } else {
181 read_vec(self.literal, LiteralRepr::read)
182 },
183 punct: read_vec(self.punct, PunctRepr::read),
184 ident: if version >= EXTENDED_LEAF_DATA {
185 read_vec(self.ident, IdentRepr::read_with_rawness)
186 } else {
187 read_vec(self.ident, IdentRepr::read)
188 },
189 token_tree: self.token_tree,
190 text: self.text,
191 span_data_table,
192 version,
193 }
194 .read_subtree()
195 }
196}
197
198#[cfg(feature = "sysroot-abi")]
199impl FlatTree {
200 pub fn from_tokenstream(
201 tokenstream: proc_macro_srv::TokenStream<Span>,
202 version: u32,
203 call_site: Span,
204 span_data_table: &mut SpanDataIndexMap,
205 ) -> FlatTree {
206 let mut w = Writer::<Span, _> {
207 string_table: FxHashMap::default(),
208 work: VecDeque::new(),
209 span_data_table,
210
211 subtree: Vec::new(),
212 literal: Vec::new(),
213 punct: Vec::new(),
214 ident: Vec::new(),
215 token_tree: Vec::new(),
216 text: Vec::new(),
217 version,
218 };
219 w.write_tokenstream(call_site, &tokenstream);
220
221 FlatTree {
222 subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
223 write_vec(w.subtree, SubtreeRepr::write_with_close_span)
224 } else {
225 write_vec(w.subtree, SubtreeRepr::write)
226 },
227 literal: if version >= EXTENDED_LEAF_DATA {
228 write_vec(w.literal, LiteralRepr::write_with_kind)
229 } else {
230 write_vec(w.literal, LiteralRepr::write)
231 },
232 punct: write_vec(w.punct, PunctRepr::write),
233 ident: if version >= EXTENDED_LEAF_DATA {
234 write_vec(w.ident, IdentRepr::write_with_rawness)
235 } else {
236 write_vec(w.ident, IdentRepr::write)
237 },
238 token_tree: w.token_tree,
239 text: w.text,
240 }
241 }
242
243 pub fn from_tokenstream_raw<T: SpanTransformer<Table = ()>>(
244 tokenstream: proc_macro_srv::TokenStream<T::Span>,
245 call_site: T::Span,
246 version: u32,
247 ) -> FlatTree {
248 let mut w = Writer::<T, _> {
249 string_table: FxHashMap::default(),
250 work: VecDeque::new(),
251 span_data_table: &mut (),
252
253 subtree: Vec::new(),
254 literal: Vec::new(),
255 punct: Vec::new(),
256 ident: Vec::new(),
257 token_tree: Vec::new(),
258 text: Vec::new(),
259 version,
260 };
261 w.write_tokenstream(call_site, &tokenstream);
262
263 FlatTree {
264 subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
265 write_vec(w.subtree, SubtreeRepr::write_with_close_span)
266 } else {
267 write_vec(w.subtree, SubtreeRepr::write)
268 },
269 literal: if version >= EXTENDED_LEAF_DATA {
270 write_vec(w.literal, LiteralRepr::write_with_kind)
271 } else {
272 write_vec(w.literal, LiteralRepr::write)
273 },
274 punct: write_vec(w.punct, PunctRepr::write),
275 ident: if version >= EXTENDED_LEAF_DATA {
276 write_vec(w.ident, IdentRepr::write_with_rawness)
277 } else {
278 write_vec(w.ident, IdentRepr::write)
279 },
280 token_tree: w.token_tree,
281 text: w.text,
282 }
283 }
284
285 pub fn to_tokenstream_unresolved<T: SpanTransformer<Table = ()>>(
286 self,
287 version: u32,
288 span_join: impl Fn(T::Span, T::Span) -> T::Span,
289 ) -> proc_macro_srv::TokenStream<T::Span> {
290 Reader::<T> {
291 subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
292 read_vec(self.subtree, SubtreeRepr::read_with_close_span)
293 } else {
294 read_vec(self.subtree, SubtreeRepr::read)
295 },
296 literal: if version >= EXTENDED_LEAF_DATA {
297 read_vec(self.literal, LiteralRepr::read_with_kind)
298 } else {
299 read_vec(self.literal, LiteralRepr::read)
300 },
301 punct: read_vec(self.punct, PunctRepr::read),
302 ident: if version >= EXTENDED_LEAF_DATA {
303 read_vec(self.ident, IdentRepr::read_with_rawness)
304 } else {
305 read_vec(self.ident, IdentRepr::read)
306 },
307 token_tree: self.token_tree,
308 text: self.text,
309 span_data_table: &(),
310 version,
311 }
312 .read_tokenstream(span_join)
313 }
314
315 pub fn to_tokenstream_resolved(
316 self,
317 version: u32,
318 span_data_table: &SpanDataIndexMap,
319 span_join: impl Fn(Span, Span) -> Span,
320 ) -> proc_macro_srv::TokenStream<Span> {
321 Reader::<Span> {
322 subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
323 read_vec(self.subtree, SubtreeRepr::read_with_close_span)
324 } else {
325 read_vec(self.subtree, SubtreeRepr::read)
326 },
327 literal: if version >= EXTENDED_LEAF_DATA {
328 read_vec(self.literal, LiteralRepr::read_with_kind)
329 } else {
330 read_vec(self.literal, LiteralRepr::read)
331 },
332 punct: read_vec(self.punct, PunctRepr::read),
333 ident: if version >= EXTENDED_LEAF_DATA {
334 read_vec(self.ident, IdentRepr::read_with_rawness)
335 } else {
336 read_vec(self.ident, IdentRepr::read)
337 },
338 token_tree: self.token_tree,
339 text: self.text,
340 span_data_table,
341 version,
342 }
343 .read_tokenstream(span_join)
344 }
345}
346
347fn read_vec<T, F: Fn([u32; N]) -> T, const N: usize>(xs: Vec<u32>, f: F) -> Vec<T> {
348 let mut chunks = xs.chunks_exact(N);
349 let res = chunks.by_ref().map(|chunk| f(chunk.try_into().unwrap())).collect();
350 assert!(chunks.remainder().is_empty());
351 res
352}
353
354fn write_vec<T, F: Fn(T) -> [u32; N], const N: usize>(xs: Vec<T>, f: F) -> Vec<u32> {
355 xs.into_iter().flat_map(f).collect()
356}
357
358impl SubtreeRepr {
359 fn write(self) -> [u32; 4] {
360 let kind = match self.kind {
361 tt::DelimiterKind::Invisible => 0,
362 tt::DelimiterKind::Parenthesis => 1,
363 tt::DelimiterKind::Brace => 2,
364 tt::DelimiterKind::Bracket => 3,
365 };
366 [self.open.0, kind, self.tt[0], self.tt[1]]
367 }
368 fn read([open, kind, lo, len]: [u32; 4]) -> SubtreeRepr {
369 let kind = match kind {
370 0 => tt::DelimiterKind::Invisible,
371 1 => tt::DelimiterKind::Parenthesis,
372 2 => tt::DelimiterKind::Brace,
373 3 => tt::DelimiterKind::Bracket,
374 other => panic!("bad kind {other}"),
375 };
376 SubtreeRepr { open: SpanId(open), close: SpanId(!0), kind, tt: [lo, len] }
377 }
378 fn write_with_close_span(self) -> [u32; 5] {
379 let kind = match self.kind {
380 tt::DelimiterKind::Invisible => 0,
381 tt::DelimiterKind::Parenthesis => 1,
382 tt::DelimiterKind::Brace => 2,
383 tt::DelimiterKind::Bracket => 3,
384 };
385 [self.open.0, self.close.0, kind, self.tt[0], self.tt[1]]
386 }
387 fn read_with_close_span([open, close, kind, lo, len]: [u32; 5]) -> SubtreeRepr {
388 let kind = match kind {
389 0 => tt::DelimiterKind::Invisible,
390 1 => tt::DelimiterKind::Parenthesis,
391 2 => tt::DelimiterKind::Brace,
392 3 => tt::DelimiterKind::Bracket,
393 other => panic!("bad kind {other}"),
394 };
395 SubtreeRepr { open: SpanId(open), close: SpanId(close), kind, tt: [lo, len] }
396 }
397}
398
399impl LiteralRepr {
400 fn write(self) -> [u32; 2] {
401 [self.id.0, self.text]
402 }
403 fn read([id, text]: [u32; 2]) -> LiteralRepr {
404 LiteralRepr { id: SpanId(id), text, kind: 0, suffix: !0 }
405 }
406 fn write_with_kind(self) -> [u32; 4] {
407 [self.id.0, self.text, self.kind as u32, self.suffix]
408 }
409 fn read_with_kind([id, text, kind, suffix]: [u32; 4]) -> LiteralRepr {
410 LiteralRepr { id: SpanId(id), text, kind: kind as u16, suffix }
411 }
412}
413
414impl PunctRepr {
415 fn write(self) -> [u32; 3] {
416 let spacing = match self.spacing {
417 tt::Spacing::Alone | tt::Spacing::JointHidden => 0,
418 tt::Spacing::Joint => 1,
419 };
420 [self.id.0, self.char as u32, spacing]
421 }
422 fn read([id, char, spacing]: [u32; 3]) -> PunctRepr {
423 let spacing = match spacing {
424 0 => tt::Spacing::Alone,
425 1 => tt::Spacing::Joint,
426 other => panic!("bad spacing {other}"),
427 };
428 PunctRepr { id: SpanId(id), char: char.try_into().unwrap(), spacing }
429 }
430}
431
432impl IdentRepr {
433 fn write(self) -> [u32; 2] {
434 [self.id.0, self.text]
435 }
436 fn read(data: [u32; 2]) -> IdentRepr {
437 IdentRepr { id: SpanId(data[0]), text: data[1], is_raw: false }
438 }
439 fn write_with_rawness(self) -> [u32; 3] {
440 [self.id.0, self.text, self.is_raw as u32]
441 }
442 fn read_with_rawness([id, text, is_raw]: [u32; 3]) -> IdentRepr {
443 IdentRepr { id: SpanId(id), text, is_raw: is_raw == 1 }
444 }
445}
446
447pub trait SpanTransformer {
448 type Table;
449 type Span: Copy;
450 fn token_id_of(table: &mut Self::Table, s: Self::Span) -> SpanId;
451 fn span_for_token_id(table: &Self::Table, id: SpanId) -> Self::Span;
452}
453impl SpanTransformer for SpanId {
454 type Table = ();
455 type Span = Self;
456 fn token_id_of((): &mut Self::Table, token_id: Self::Span) -> SpanId {
457 token_id
458 }
459
460 fn span_for_token_id((): &Self::Table, id: SpanId) -> Self::Span {
461 id
462 }
463}
464impl SpanTransformer for Span {
465 type Table = SpanDataIndexMap;
466 type Span = Self;
467 fn token_id_of(table: &mut Self::Table, span: Self::Span) -> SpanId {
468 SpanId(table.insert_full(span).0 as u32)
469 }
470 fn span_for_token_id(table: &Self::Table, id: SpanId) -> Self::Span {
471 *table.get_index(id.0 as usize).unwrap_or_else(|| &table[0])
472 }
473}
474
475struct Writer<'a, 'span, S: SpanTransformer, W> {
476 work: VecDeque<(usize, usize, W)>,
477 string_table: FxHashMap<std::borrow::Cow<'a, str>, u32>,
478 span_data_table: &'span mut S::Table,
479 version: u32,
480
481 subtree: Vec<SubtreeRepr>,
482 literal: Vec<LiteralRepr>,
483 punct: Vec<PunctRepr>,
484 ident: Vec<IdentRepr>,
485 token_tree: Vec<u32>,
486 text: Vec<String>,
487}
488
489impl<'a, T: SpanTransformer> Writer<'a, '_, T, tt::iter::TtIter<'a, T::Span>> {
490 fn write_subtree(&mut self, root: tt::SubtreeView<'a, T::Span>) {
491 let subtree = root.top_subtree();
492 self.enqueue(subtree, root.iter());
493 while let Some((idx, len, subtree)) = self.work.pop_front() {
494 self.subtree(idx, len, subtree);
495 }
496 }
497
498 fn subtree(&mut self, idx: usize, n_tt: usize, subtree: tt::iter::TtIter<'a, T::Span>) {
499 let mut first_tt = self.token_tree.len();
500 self.token_tree.resize(first_tt + n_tt, !0);
501
502 self.subtree[idx].tt = [first_tt as u32, (first_tt + n_tt) as u32];
503
504 for child in subtree {
505 let idx_tag = match child {
506 tt::iter::TtElement::Subtree(subtree, subtree_iter) => {
507 let idx = self.enqueue(subtree, subtree_iter);
508 idx << 2
509 }
510 tt::iter::TtElement::Leaf(leaf) => match leaf {
511 tt::Leaf::Literal(lit) => {
512 let idx = self.literal.len() as u32;
513 let id = self.token_id_of(lit.span);
514 let (text, suffix) = if self.version >= EXTENDED_LEAF_DATA {
515 (
516 self.intern(lit.symbol.as_str()),
517 lit.suffix.as_ref().map(|s| self.intern(s.as_str())).unwrap_or(!0),
518 )
519 } else {
520 (self.intern_owned(format!("{lit}")), !0)
521 };
522 self.literal.push(LiteralRepr {
523 id,
524 text,
525 kind: u16::from_le_bytes(match lit.kind {
526 tt::LitKind::Err(_) => [0, 0],
527 tt::LitKind::Byte => [1, 0],
528 tt::LitKind::Char => [2, 0],
529 tt::LitKind::Integer => [3, 0],
530 tt::LitKind::Float => [4, 0],
531 tt::LitKind::Str => [5, 0],
532 tt::LitKind::StrRaw(r) => [6, r],
533 tt::LitKind::ByteStr => [7, 0],
534 tt::LitKind::ByteStrRaw(r) => [8, r],
535 tt::LitKind::CStr => [9, 0],
536 tt::LitKind::CStrRaw(r) => [10, r],
537 }),
538 suffix,
539 });
540 (idx << 2) | 0b01
541 }
542 tt::Leaf::Punct(punct) => {
543 let idx = self.punct.len() as u32;
544 let id = self.token_id_of(punct.span);
545 self.punct.push(PunctRepr { char: punct.char, spacing: punct.spacing, id });
546 (idx << 2) | 0b10
547 }
548 tt::Leaf::Ident(ident) => {
549 let idx = self.ident.len() as u32;
550 let id = self.token_id_of(ident.span);
551 let text = if self.version >= EXTENDED_LEAF_DATA {
552 self.intern(ident.sym.as_str())
553 } else if ident.is_raw.yes() {
554 self.intern_owned(format!("r#{}", ident.sym.as_str(),))
555 } else {
556 self.intern(ident.sym.as_str())
557 };
558 self.ident.push(IdentRepr { id, text, is_raw: ident.is_raw.yes() });
559 (idx << 2) | 0b11
560 }
561 },
562 };
563 self.token_tree[first_tt] = idx_tag;
564 first_tt += 1;
565 }
566 }
567
568 fn enqueue(
569 &mut self,
570 subtree: &'a tt::Subtree<T::Span>,
571 contents: tt::iter::TtIter<'a, T::Span>,
572 ) -> u32 {
573 let idx = self.subtree.len();
574 let open = self.token_id_of(subtree.delimiter.open);
575 let close = self.token_id_of(subtree.delimiter.close);
576 let delimiter_kind = subtree.delimiter.kind;
577 self.subtree.push(SubtreeRepr { open, close, kind: delimiter_kind, tt: [!0, !0] });
578 self.work.push_back((idx, contents.clone().count(), contents));
580 idx as u32
581 }
582}
583
584impl<'a, T: SpanTransformer, U> Writer<'a, '_, T, U> {
585 fn token_id_of(&mut self, span: T::Span) -> SpanId {
586 T::token_id_of(self.span_data_table, span)
587 }
588
589 pub(crate) fn intern(&mut self, text: &'a str) -> u32 {
590 let table = &mut self.text;
591 *self.string_table.entry(text.into()).or_insert_with(|| {
592 let idx = table.len();
593 table.push(text.to_owned());
594 idx as u32
595 })
596 }
597
598 pub(crate) fn intern_owned(&mut self, text: String) -> u32 {
599 let table = &mut self.text;
600 *self.string_table.entry(text.clone().into()).or_insert_with(|| {
601 let idx = table.len();
602 table.push(text);
603 idx as u32
604 })
605 }
606}
607
608#[cfg(feature = "sysroot-abi")]
609impl<'a, T: SpanTransformer>
610 Writer<'a, '_, T, Option<proc_macro_srv::TokenStreamIter<'a, T::Span>>>
611{
612 fn write_tokenstream(
613 &mut self,
614 call_site: T::Span,
615 root: &'a proc_macro_srv::TokenStream<T::Span>,
616 ) {
617 let call_site = self.token_id_of(call_site);
618 if let Some(group) = root.as_single_group() {
619 self.enqueue(group);
620 } else {
621 self.subtree.push(SubtreeRepr {
622 open: call_site,
623 close: call_site,
624 kind: tt::DelimiterKind::Invisible,
625 tt: [!0, !0],
626 });
627 self.work.push_back((0, root.len(), Some(root.iter())));
628 }
629 while let Some((idx, len, group)) = self.work.pop_front() {
630 self.group(idx, len, group);
631 }
632 }
633
634 fn group(
635 &mut self,
636 idx: usize,
637 n_tt: usize,
638 group: Option<proc_macro_srv::TokenStreamIter<'a, T::Span>>,
639 ) {
640 let mut first_tt = self.token_tree.len();
641 self.token_tree.resize(first_tt + n_tt, !0);
642
643 self.subtree[idx].tt = [first_tt as u32, (first_tt + n_tt) as u32];
644
645 for tt in group.into_iter().flatten() {
646 let idx_tag = match tt {
647 proc_macro_srv::TokenTree::Group(group) => {
648 let idx = self.enqueue(group);
649 idx << 2
650 }
651 proc_macro_srv::TokenTree::Literal(lit) => {
652 let idx = self.literal.len() as u32;
653 let id = self.token_id_of(lit.span);
654 let (text, suffix) = if self.version >= EXTENDED_LEAF_DATA {
655 (
656 self.intern(lit.symbol.as_str()),
657 lit.suffix.as_ref().map(|s| self.intern(s.as_str())).unwrap_or(!0),
658 )
659 } else {
660 (self.intern_owned(proc_macro_srv::literal_to_string(lit)), !0)
661 };
662 self.literal.push(LiteralRepr {
663 id,
664 text,
665 kind: u16::from_le_bytes(match lit.kind {
666 proc_macro_srv::LitKind::ErrWithGuar => [0, 0],
667 proc_macro_srv::LitKind::Byte => [1, 0],
668 proc_macro_srv::LitKind::Char => [2, 0],
669 proc_macro_srv::LitKind::Integer => [3, 0],
670 proc_macro_srv::LitKind::Float => [4, 0],
671 proc_macro_srv::LitKind::Str => [5, 0],
672 proc_macro_srv::LitKind::StrRaw(r) => [6, r],
673 proc_macro_srv::LitKind::ByteStr => [7, 0],
674 proc_macro_srv::LitKind::ByteStrRaw(r) => [8, r],
675 proc_macro_srv::LitKind::CStr => [9, 0],
676 proc_macro_srv::LitKind::CStrRaw(r) => [10, r],
677 }),
678 suffix,
679 });
680 (idx << 2) | 0b01
681 }
682 proc_macro_srv::TokenTree::Punct(punct) => {
683 let idx = self.punct.len() as u32;
684 let id = self.token_id_of(punct.span);
685 self.punct.push(PunctRepr {
686 char: punct.ch as char,
687 spacing: if punct.joint { tt::Spacing::Joint } else { tt::Spacing::Alone },
688 id,
689 });
690 (idx << 2) | 0b10
691 }
692 proc_macro_srv::TokenTree::Ident(ident) => {
693 let idx = self.ident.len() as u32;
694 let id = self.token_id_of(ident.span);
695 let text = if self.version >= EXTENDED_LEAF_DATA {
696 self.intern(ident.sym.as_str())
697 } else if ident.is_raw {
698 self.intern_owned(format!("r#{}", ident.sym.as_str(),))
699 } else {
700 self.intern(ident.sym.as_str())
701 };
702 self.ident.push(IdentRepr { id, text, is_raw: ident.is_raw });
703 (idx << 2) | 0b11
704 }
705 };
706 self.token_tree[first_tt] = idx_tag;
707 first_tt += 1;
708 }
709 }
710
711 fn enqueue(&mut self, group: &'a proc_macro_srv::Group<T::Span>) -> u32 {
712 let idx = self.subtree.len();
713 let open = self.token_id_of(group.span.open);
714 let close = self.token_id_of(group.span.close);
715 let delimiter_kind = match group.delimiter {
716 proc_macro_srv::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
717 proc_macro_srv::Delimiter::Brace => tt::DelimiterKind::Brace,
718 proc_macro_srv::Delimiter::Bracket => tt::DelimiterKind::Bracket,
719 proc_macro_srv::Delimiter::None => tt::DelimiterKind::Invisible,
720 };
721 self.subtree.push(SubtreeRepr { open, close, kind: delimiter_kind, tt: [!0, !0] });
722 self.work.push_back((
723 idx,
724 group.stream.as_ref().map_or(0, |stream| stream.len()),
725 group.stream.as_ref().map(|ts| ts.iter()),
726 ));
727 idx as u32
728 }
729}
730
731struct Reader<'span, S: SpanTransformer> {
732 version: u32,
733 subtree: Vec<SubtreeRepr>,
734 literal: Vec<LiteralRepr>,
735 punct: Vec<PunctRepr>,
736 ident: Vec<IdentRepr>,
737 token_tree: Vec<u32>,
738 text: Vec<String>,
739 span_data_table: &'span S::Table,
740}
741
742impl<T: SpanTransformer> Reader<'_, T> {
743 pub(crate) fn read_subtree(self) -> tt::TopSubtree<T::Span> {
744 let mut res: Vec<Option<(tt::Delimiter<T::Span>, Vec<tt::TokenTree<T::Span>>)>> =
745 vec![None; self.subtree.len()];
746 let read_span = |id| T::span_for_token_id(self.span_data_table, id);
747 for i in (0..self.subtree.len()).rev() {
748 let repr = &self.subtree[i];
749 let token_trees = &self.token_tree[repr.tt[0] as usize..repr.tt[1] as usize];
750 let delimiter = tt::Delimiter {
751 open: read_span(repr.open),
752 close: read_span(repr.close),
753 kind: repr.kind,
754 };
755 let mut s = Vec::new();
756 for &idx_tag in token_trees {
757 let tag = idx_tag & 0b11;
758 let idx = (idx_tag >> 2) as usize;
759 match tag {
760 0b00 => {
763 let (delimiter, subtree) = res[idx].take().unwrap();
764 s.push(tt::TokenTree::Subtree(tt::Subtree {
765 delimiter,
766 len: subtree.len() as u32,
767 }));
768 s.extend(subtree)
769 }
770 0b01 => {
771 use tt::LitKind::*;
772 let repr = &self.literal[idx];
773 let text = self.text[repr.text as usize].as_str();
774 let span = read_span(repr.id);
775 s.push(
776 tt::Leaf::Literal(if self.version >= EXTENDED_LEAF_DATA {
777 tt::Literal {
778 symbol: Symbol::intern(text),
779 span,
780 kind: match u16::to_le_bytes(repr.kind) {
781 [0, _] => Err(()),
782 [1, _] => Byte,
783 [2, _] => Char,
784 [3, _] => Integer,
785 [4, _] => Float,
786 [5, _] => Str,
787 [6, r] => StrRaw(r),
788 [7, _] => ByteStr,
789 [8, r] => ByteStrRaw(r),
790 [9, _] => CStr,
791 [10, r] => CStrRaw(r),
792 _ => unreachable!(),
793 },
794 suffix: if repr.suffix != !0 {
795 Some(Symbol::intern(
796 self.text[repr.suffix as usize].as_str(),
797 ))
798 } else {
799 None
800 },
801 }
802 } else {
803 tt::token_to_literal(text, span)
804 })
805 .into(),
806 )
807 }
808 0b10 => {
809 let repr = &self.punct[idx];
810 s.push(
811 tt::Leaf::Punct(tt::Punct {
812 char: repr.char,
813 spacing: repr.spacing,
814 span: read_span(repr.id),
815 })
816 .into(),
817 )
818 }
819 0b11 => {
820 let repr = &self.ident[idx];
821 let text = self.text[repr.text as usize].as_str();
822 let (is_raw, text) = if self.version >= EXTENDED_LEAF_DATA {
823 (
824 if repr.is_raw { tt::IdentIsRaw::Yes } else { tt::IdentIsRaw::No },
825 text,
826 )
827 } else {
828 tt::IdentIsRaw::split_from_symbol(text)
829 };
830 s.push(
831 tt::Leaf::Ident(tt::Ident {
832 sym: Symbol::intern(text),
833 span: read_span(repr.id),
834 is_raw,
835 })
836 .into(),
837 )
838 }
839 other => panic!("bad tag: {other}"),
840 }
841 }
842 res[i] = Some((delimiter, s));
843 }
844
845 let (delimiter, mut res) = res[0].take().unwrap();
846 res.insert(0, tt::TokenTree::Subtree(tt::Subtree { delimiter, len: res.len() as u32 }));
847 tt::TopSubtree(res.into_boxed_slice())
848 }
849}
850
851#[cfg(feature = "sysroot-abi")]
852impl<T: SpanTransformer> Reader<'_, T> {
853 pub(crate) fn read_tokenstream(
854 self,
855 span_join: impl Fn(T::Span, T::Span) -> T::Span,
856 ) -> proc_macro_srv::TokenStream<T::Span> {
857 let mut res: Vec<Option<proc_macro_srv::Group<T::Span>>> = vec![None; self.subtree.len()];
858 let read_span = |id| T::span_for_token_id(self.span_data_table, id);
859 for i in (0..self.subtree.len()).rev() {
860 let repr = &self.subtree[i];
861 let token_trees = &self.token_tree[repr.tt[0] as usize..repr.tt[1] as usize];
862
863 let stream = token_trees
864 .iter()
865 .copied()
866 .map(|idx_tag| {
867 let tag = idx_tag & 0b11;
868 let idx = (idx_tag >> 2) as usize;
869 match tag {
870 0b00 => proc_macro_srv::TokenTree::Group(res[idx].take().unwrap()),
873 0b01 => {
874 let repr = &self.literal[idx];
875 let text = self.text[repr.text as usize].as_str();
876 let span = read_span(repr.id);
877 proc_macro_srv::TokenTree::Literal(
878 if self.version >= EXTENDED_LEAF_DATA {
879 proc_macro_srv::Literal {
880 symbol: Symbol::intern(text),
881 span,
882 kind: match u16::to_le_bytes(repr.kind) {
883 [0, _] => proc_macro_srv::LitKind::ErrWithGuar,
884 [1, _] => proc_macro_srv::LitKind::Byte,
885 [2, _] => proc_macro_srv::LitKind::Char,
886 [3, _] => proc_macro_srv::LitKind::Integer,
887 [4, _] => proc_macro_srv::LitKind::Float,
888 [5, _] => proc_macro_srv::LitKind::Str,
889 [6, r] => proc_macro_srv::LitKind::StrRaw(r),
890 [7, _] => proc_macro_srv::LitKind::ByteStr,
891 [8, r] => proc_macro_srv::LitKind::ByteStrRaw(r),
892 [9, _] => proc_macro_srv::LitKind::CStr,
893 [10, r] => proc_macro_srv::LitKind::CStrRaw(r),
894 _ => unreachable!(),
895 },
896 suffix: if repr.suffix != !0 {
897 Some(Symbol::intern(
898 self.text[repr.suffix as usize].as_str(),
899 ))
900 } else {
901 None
902 },
903 }
904 } else {
905 proc_macro_srv::literal_from_str(text, span).unwrap_or_else(
906 |_| proc_macro_srv::Literal {
907 symbol: Symbol::intern("internal error"),
908 span,
909 kind: proc_macro_srv::LitKind::ErrWithGuar,
910 suffix: None,
911 },
912 )
913 },
914 )
915 }
916 0b10 => {
917 let repr = &self.punct[idx];
918 proc_macro_srv::TokenTree::Punct(proc_macro_srv::Punct {
919 ch: repr.char as u8,
920 joint: repr.spacing == tt::Spacing::Joint,
921 span: read_span(repr.id),
922 })
923 }
924 0b11 => {
925 let repr = &self.ident[idx];
926 let text = self.text[repr.text as usize].as_str();
927 let (is_raw, text) = if self.version >= EXTENDED_LEAF_DATA {
928 (
929 if repr.is_raw {
930 tt::IdentIsRaw::Yes
931 } else {
932 tt::IdentIsRaw::No
933 },
934 text,
935 )
936 } else {
937 tt::IdentIsRaw::split_from_symbol(text)
938 };
939 proc_macro_srv::TokenTree::Ident(proc_macro_srv::Ident {
940 sym: Symbol::intern(text),
941 span: read_span(repr.id),
942 is_raw: is_raw.yes(),
943 })
944 }
945 other => panic!("bad tag: {other}"),
946 }
947 })
948 .collect::<Vec<_>>();
949 let open = read_span(repr.open);
950 let close = read_span(repr.close);
951 let g = proc_macro_srv::Group {
952 delimiter: match repr.kind {
953 tt::DelimiterKind::Parenthesis => proc_macro_srv::Delimiter::Parenthesis,
954 tt::DelimiterKind::Brace => proc_macro_srv::Delimiter::Brace,
955 tt::DelimiterKind::Bracket => proc_macro_srv::Delimiter::Bracket,
956 tt::DelimiterKind::Invisible => proc_macro_srv::Delimiter::None,
957 },
958 stream: if stream.is_empty() { None } else { Some(TokenStream::new(stream)) },
959 span: proc_macro_srv::DelimSpan {
960 open,
961 close,
962 entire: span_join(open, close),
964 },
965 };
966 res[i] = Some(g);
967 }
968 let group = res[0].take().unwrap();
969 if group.delimiter == proc_macro_srv::Delimiter::None {
970 group.stream.unwrap_or_default()
971 } else {
972 TokenStream::new(vec![proc_macro_srv::TokenTree::Group(group)])
973 }
974 }
975}