aboutsummaryrefslogtreecommitdiff
path: root/libgrust/libproc_macro
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2023-08-28 17:20:28 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-16 19:04:32 +0100
commitb1c722d1411448e00d45bb4da0aca2421dcd54e0 (patch)
treeb11715e039833ce6ebc83a6ff284a2b69ae5296b /libgrust/libproc_macro
parentfd73cf8c31611dd8ddbf7835ce246e56771618ef (diff)
downloadgcc-b1c722d1411448e00d45bb4da0aca2421dcd54e0.zip
gcc-b1c722d1411448e00d45bb4da0aca2421dcd54e0.tar.gz
gcc-b1c722d1411448e00d45bb4da0aca2421dcd54e0.tar.bz2
gccrs: libproc_macro: Split c++ and rust
Move the rust interface to the libproc_macro directory. libgrust/ChangeLog: * libproc_macro_internal/rust/bridge.rs: Moved to... * libproc_macro/bridge.rs: ...here. * libproc_macro_internal/rust/bridge/ffistring.rs: Moved to... * libproc_macro/bridge/ffistring.rs: ...here. * libproc_macro_internal/rust/bridge/group.rs: Moved to... * libproc_macro/bridge/group.rs: ...here. * libproc_macro_internal/rust/bridge/ident.rs: Moved to... * libproc_macro/bridge/ident.rs: ...here. * libproc_macro_internal/rust/bridge/literal.rs: Moved to... * libproc_macro/bridge/literal.rs: ...here. * libproc_macro_internal/rust/bridge/punct.rs: Moved to... * libproc_macro/bridge/punct.rs: ...here. * libproc_macro_internal/rust/bridge/span.rs: Moved to... * libproc_macro/bridge/span.rs: ...here. * libproc_macro_internal/rust/bridge/token_stream.rs: Moved to... * libproc_macro/bridge/token_stream.rs: ...here. * libproc_macro_internal/rust/group.rs: Moved to... * libproc_macro/group.rs: ...here. * libproc_macro_internal/rust/ident.rs: Moved to... * libproc_macro/ident.rs: ...here. * libproc_macro_internal/rust/lib.rs: Moved to... * libproc_macro/lib.rs: ...here. * libproc_macro_internal/rust/literal.rs: Moved to... * libproc_macro/literal.rs: ...here. * libproc_macro_internal/rust/punct.rs: Moved to... * libproc_macro/punct.rs: ...here. * libproc_macro_internal/rust/span.rs: Moved to... * libproc_macro/span.rs: ...here. * libproc_macro_internal/rust/token_stream.rs: Moved to... * libproc_macro/token_stream.rs: ...here. Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Diffstat (limited to 'libgrust/libproc_macro')
-rw-r--r--libgrust/libproc_macro/bridge.rs15
-rw-r--r--libgrust/libproc_macro/bridge/ffistring.rs51
-rw-r--r--libgrust/libproc_macro/bridge/group.rs60
-rw-r--r--libgrust/libproc_macro/bridge/ident.rs58
-rw-r--r--libgrust/libproc_macro/bridge/literal.rs241
-rw-r--r--libgrust/libproc_macro/bridge/punct.rs39
-rw-r--r--libgrust/libproc_macro/bridge/span.rs40
-rw-r--r--libgrust/libproc_macro/bridge/token_stream.rs156
-rw-r--r--libgrust/libproc_macro/group.rs88
-rw-r--r--libgrust/libproc_macro/ident.rs67
-rw-r--r--libgrust/libproc_macro/lib.rs198
-rw-r--r--libgrust/libproc_macro/literal.rs189
-rw-r--r--libgrust/libproc_macro/punct.rs92
-rw-r--r--libgrust/libproc_macro/span.rs52
-rw-r--r--libgrust/libproc_macro/token_stream.rs52
15 files changed, 1398 insertions, 0 deletions
diff --git a/libgrust/libproc_macro/bridge.rs b/libgrust/libproc_macro/bridge.rs
new file mode 100644
index 0000000..3900ae1
--- /dev/null
+++ b/libgrust/libproc_macro/bridge.rs
@@ -0,0 +1,15 @@
+pub mod ffistring;
+pub mod group;
+pub mod ident;
+pub mod literal;
+pub mod punct;
+pub mod span;
+pub mod token_stream;
+
+extern "C" {
+ fn bridge__is_available() -> bool;
+}
+
+pub fn is_available() -> bool {
+ unsafe { bridge__is_available() }
+}
diff --git a/libgrust/libproc_macro/bridge/ffistring.rs b/libgrust/libproc_macro/bridge/ffistring.rs
new file mode 100644
index 0000000..73162e9
--- /dev/null
+++ b/libgrust/libproc_macro/bridge/ffistring.rs
@@ -0,0 +1,51 @@
+use std::convert::TryInto;
+use std::ffi::c_uchar;
+use std::fmt;
+use std::slice::from_raw_parts;
+use std::str::from_utf8;
+
+extern "C" {
+ fn FFIString__new(data: *const c_uchar, len: u64) -> FFIString;
+ fn FFIString__drop(string: *mut FFIString);
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct FFIString {
+ data: *const c_uchar,
+ len: u64,
+}
+
+impl<S> From<S> for FFIString
+where
+ S: AsRef<str>,
+{
+ fn from(s: S) -> Self {
+ unsafe { FFIString__new(s.as_ref().as_ptr(), s.as_ref().len() as u64) }
+ }
+}
+
+impl Clone for FFIString {
+ fn clone(&self) -> Self {
+ FFIString::from(&self.to_string())
+ }
+}
+
+impl Drop for FFIString {
+ fn drop(&mut self) {
+ unsafe {
+ FFIString__drop(self as *mut FFIString);
+ }
+ }
+}
+
+impl fmt::Display for FFIString {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(
+ from_utf8(unsafe {
+ from_raw_parts(self.data, self.len.try_into().map_err(|_| fmt::Error)?)
+ })
+ .map_err(|_| fmt::Error)?,
+ )
+ }
+}
diff --git a/libgrust/libproc_macro/bridge/group.rs b/libgrust/libproc_macro/bridge/group.rs
new file mode 100644
index 0000000..254a3db
--- /dev/null
+++ b/libgrust/libproc_macro/bridge/group.rs
@@ -0,0 +1,60 @@
+use bridge::span::Span;
+use bridge::token_stream::TokenStream;
+use std::fmt;
+use Delimiter;
+
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct Group {
+ delimiter: Delimiter,
+ stream: TokenStream,
+ span: Span,
+}
+
+impl Group {
+ pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
+ Group {
+ delimiter,
+ stream,
+ span: Span::default(),
+ }
+ }
+
+ pub fn delimiter(&self) -> Delimiter {
+ self.delimiter
+ }
+
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ let _ = span;
+ }
+
+ pub fn stream(&self) -> TokenStream {
+ self.stream.clone()
+ }
+}
+
+impl fmt::Display for Group {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.delimiter {
+ Delimiter::Parenthesis => f.write_str("(")?,
+ Delimiter::Brace => f.write_str("{")?,
+ Delimiter::Bracket => f.write_str("[")?,
+ Delimiter::None => (),
+ }
+
+ self.stream.fmt(f)?;
+
+ match self.delimiter {
+ Delimiter::Parenthesis => f.write_str(")")?,
+ Delimiter::Brace => f.write_str("}")?,
+ Delimiter::Bracket => f.write_str("]")?,
+ Delimiter::None => (),
+ }
+
+ Ok(())
+ }
+}
diff --git a/libgrust/libproc_macro/bridge/ident.rs b/libgrust/libproc_macro/bridge/ident.rs
new file mode 100644
index 0000000..d58896d
--- /dev/null
+++ b/libgrust/libproc_macro/bridge/ident.rs
@@ -0,0 +1,58 @@
+use bridge::ffistring::FFIString;
+use bridge::span::Span;
+use std::fmt;
+
+extern "C" {
+ fn Ident__new(str: FFIString, span: Span) -> Ident;
+ fn Ident__new_raw(str: FFIString, span: Span) -> Ident;
+ fn Ident__drop(ident: *mut Ident);
+ fn Ident__clone(ident: *const Ident) -> Ident;
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct Ident {
+ pub(crate) is_raw: bool,
+ value: FFIString,
+ span: Span,
+}
+
+impl Ident {
+ pub fn new(string: &str, span: Span) -> Self {
+ unsafe { Ident__new(string.into(), span) }
+ }
+
+ pub fn new_raw(string: &str, span: Span) -> Self {
+ unsafe { Ident__new_raw(string.into(), span) }
+ }
+
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+}
+
+impl Drop for Ident {
+ fn drop(&mut self) {
+ unsafe { Ident__drop(self as *mut Ident) }
+ }
+}
+
+impl fmt::Display for Ident {
+ /// Display as lossless converted string.
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.is_raw {
+ f.write_str("r#")?;
+ }
+ self.value.fmt(f)
+ }
+}
+
+impl Clone for Ident {
+ fn clone(&self) -> Self {
+ unsafe { Ident__clone(self as *const Ident) }
+ }
+}
diff --git a/libgrust/libproc_macro/bridge/literal.rs b/libgrust/libproc_macro/bridge/literal.rs
new file mode 100644
index 0000000..5982504
--- /dev/null
+++ b/libgrust/libproc_macro/bridge/literal.rs
@@ -0,0 +1,241 @@
+use bridge::{ffistring::FFIString, span::Span};
+use std::fmt;
+use std::str::FromStr;
+use LexError;
+
+extern "C" {
+ fn Literal__from_string(str: FFIString, lit: *mut Literal) -> bool;
+}
+
+#[repr(C)]
+#[derive(Debug, Clone, Copy)]
+pub enum LitKind {
+ Byte,
+ Char,
+ Integer,
+ Float,
+ Str,
+ StrRaw(u8),
+ ByteStr,
+ ByteStrRaw(u8),
+ Err,
+}
+
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct Literal {
+ kind: LitKind,
+ text: FFIString,
+ suffix: FFIString,
+ span: Span,
+}
+
+macro_rules! suffixed_int_literals {
+ ($($name: ident => $kind: ident,)*) => ($(
+ pub fn $name(n : $kind) -> Literal {
+ Literal {
+ kind : LitKind::Integer,
+ text: FFIString::from(&n.to_string()),
+ suffix: FFIString::from(stringify!($kind)),
+ span: Span::default(),
+ }
+ }
+ )*)
+}
+
+macro_rules! unsuffixed_int_literals {
+ ($($name: ident => $kind: ident,)*) => ($(
+ pub fn $name(n : $kind) -> Literal {
+ Literal {
+ kind : LitKind::Integer,
+ text: FFIString::from(&n.to_string()),
+ suffix: FFIString::from(""),
+ span: Span::default(),
+ }
+ }
+ )*)
+}
+
+impl Literal {
+ suffixed_int_literals! {
+ u8_suffixed => u8,
+ u16_suffixed => u16,
+ u32_suffixed => u32,
+ u64_suffixed => u64,
+ u128_suffixed => u128,
+ usize_suffixed => usize,
+ i8_suffixed => i8,
+ i16_suffixed => i16,
+ i32_suffixed => i32,
+ i64_suffixed => i64,
+ i128_suffixed => i128,
+ isize_suffixed => isize,
+ }
+
+ unsuffixed_int_literals! {
+ u8_unsuffixed => u8,
+ u16_unsuffixed => u16,
+ u32_unsuffixed => u32,
+ u64_unsuffixed => u64,
+ u128_unsuffixed => u128,
+ usize_unsuffixed => usize,
+ i8_unsuffixed => i8,
+ i16_unsuffixed => i16,
+ i32_unsuffixed => i32,
+ i64_unsuffixed => i64,
+ i128_unsuffixed => i128,
+ isize_unsuffixed => isize,
+ }
+
+ pub fn f32_unsuffixed(n: f32) -> Self {
+ let mut repr = n.to_string();
+ if !repr.contains('.') {
+ repr.push_str(".0");
+ }
+
+ Literal {
+ kind: LitKind::Float,
+ text: FFIString::from(&repr),
+ suffix: FFIString::from(""),
+ span: Span::default(),
+ }
+ }
+
+ pub fn f32_suffixed(n: f32) -> Self {
+ Literal {
+ kind: LitKind::Float,
+ text: FFIString::from(&n.to_string()),
+ suffix: FFIString::from("f32"),
+ span: Span::default(),
+ }
+ }
+
+ pub fn f64_unsuffixed(n: f64) -> Self {
+ let mut repr = n.to_string();
+ if !repr.contains('.') {
+ repr.push_str(".0");
+ }
+
+ Literal {
+ kind: LitKind::Float,
+ text: FFIString::from(&repr),
+ suffix: FFIString::from(""),
+ span: Span::default(),
+ }
+ }
+
+ pub fn f64_suffixed(n: f64) -> Self {
+ Literal {
+ kind: LitKind::Float,
+ text: FFIString::from(&n.to_string()),
+ suffix: FFIString::from("f64"),
+ span: Span::default(),
+ }
+ }
+
+ pub fn string(string: &str) -> Self {
+ Literal {
+ kind: LitKind::Str,
+ text: FFIString::from(string),
+ suffix: FFIString::from(""),
+ span: Span::default(),
+ }
+ }
+
+ pub fn character(c: char) -> Self {
+ Literal {
+ kind: LitKind::Char,
+ text: FFIString::from(&c.to_string()),
+ suffix: FFIString::from(""),
+ span: Span::default(),
+ }
+ }
+
+ pub fn byte_string(bytes: &[u8]) -> Self {
+ Literal {
+ kind: LitKind::ByteStr,
+ text: FFIString::from(&bytes.escape_ascii().to_string()),
+ suffix: FFIString::from(""),
+ span: Span::default(),
+ }
+ }
+
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+}
+
+impl fmt::Display for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let text = &self.text.to_string();
+ match self.kind {
+ LitKind::Byte => {
+ f.write_str("b'")?;
+ f.write_str(text)?;
+ f.write_str("'")?;
+ }
+ LitKind::Char => {
+ f.write_str("'")?;
+ f.write_str(text)?;
+ f.write_str("'")?;
+ }
+ LitKind::Str => {
+ f.write_str("\"")?;
+ f.write_str(text)?;
+ f.write_str("\"")?;
+ }
+ LitKind::StrRaw(n) => {
+ f.write_str("r")?;
+ for _ in 0..n {
+ f.write_str("#")?;
+ }
+ f.write_str("\"")?;
+ f.write_str(text)?;
+ f.write_str("\"")?;
+ }
+ LitKind::ByteStr => {
+ f.write_str("b\"")?;
+ f.write_str(text)?;
+ f.write_str("\"")?;
+ }
+ LitKind::ByteStrRaw(n) => {
+ f.write_str("br")?;
+ for _ in 0..n {
+ f.write_str("#")?;
+ }
+ f.write_str("\"")?;
+ f.write_str(text)?;
+ f.write_str("\"")?;
+ }
+ _ => f.write_str(text)?,
+ }
+
+ f.write_str(&self.suffix.to_string())?;
+ Ok(())
+ }
+}
+
+impl FromStr for Literal {
+ type Err = LexError;
+
+ fn from_str(string: &str) -> Result<Self, LexError> {
+ // Structure that will be filled in by the cpp
+ let mut lit = Literal {
+ kind: LitKind::Err,
+ text: FFIString::from(""),
+ suffix: FFIString::from(""),
+ span: Span::default(),
+ };
+ // TODO: We might want to pass a LexError by reference to retrieve
+ // error information
+ if unsafe { Literal__from_string(string.into(), &mut lit as *mut Literal) } {
+ Err(LexError)
+ } else {
+ Ok(lit)
+ }
+ }
+}
diff --git a/libgrust/libproc_macro/bridge/punct.rs b/libgrust/libproc_macro/bridge/punct.rs
new file mode 100644
index 0000000..e835472
--- /dev/null
+++ b/libgrust/libproc_macro/bridge/punct.rs
@@ -0,0 +1,39 @@
+use bridge::span::Span;
+use std::convert::TryFrom;
+use std::fmt;
+use Spacing;
+
+#[repr(C)]
+#[derive(Clone, Debug)]
+pub struct Punct {
+ pub(crate) ch: u32,
+ pub(crate) spacing: Spacing,
+ span: Span,
+}
+
+impl Punct {
+ pub fn new(ch: char, spacing: Spacing) -> Self {
+ Punct {
+ ch: ch.into(),
+ spacing,
+ span: Span::default(),
+ }
+ }
+
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ let _ = span;
+ }
+}
+
+impl fmt::Display for Punct {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Spacing::Alone = self.spacing {
+ f.write_str(" ")?;
+ }
+ char::try_from(self.ch).unwrap().fmt(f)
+ }
+}
diff --git a/libgrust/libproc_macro/bridge/span.rs b/libgrust/libproc_macro/bridge/span.rs
new file mode 100644
index 0000000..06537c9
--- /dev/null
+++ b/libgrust/libproc_macro/bridge/span.rs
@@ -0,0 +1,40 @@
+//! Bridge internal span representation and functions
+//!
+//! # Note
+//!
+//! All methods accessing source location in rust are unstable, hence this
+//! implementation with an empty structure.
+
+/// # Note: Gcc does not have a span interner, a span will not contain an index
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(C)]
+pub struct Span {
+ location: u32,
+}
+
+impl Span {
+ pub fn call_site() -> Self {
+ // FIXME: implement this function properly
+ Span::default()
+ }
+
+ pub fn mixed_site() -> Self {
+ // FIXME: implement this function properly
+ Span::default()
+ }
+
+ pub fn resolved_at(&self, _other: Span) -> Self {
+ // FIXME: implement this function properly
+ Span::default()
+ }
+
+ pub fn located_at(&self, _other: Span) -> Self {
+ // FIXME: implement this function properly
+ Span::default()
+ }
+
+ pub fn source_text(&self) -> Option<String> {
+ // FIXME: implement this function properly
+ None
+ }
+}
diff --git a/libgrust/libproc_macro/bridge/token_stream.rs b/libgrust/libproc_macro/bridge/token_stream.rs
new file mode 100644
index 0000000..094f91f
--- /dev/null
+++ b/libgrust/libproc_macro/bridge/token_stream.rs
@@ -0,0 +1,156 @@
+use bridge::{ffistring::FFIString, group::Group, ident::Ident, literal::Literal, punct::Punct};
+use std::convert::TryInto;
+use std::fmt;
+use std::slice;
+use std::str::FromStr;
+use LexError;
+
+type ExternalTokenTree = crate::TokenTree;
+type ExternalTokenStream = crate::TokenStream;
+
+extern "C" {
+ fn TokenStream__new() -> TokenStream;
+ fn TokenStream__with_capacity(capacity: u64) -> TokenStream;
+ fn TokenStream__push(stream: *mut TokenStream, tree: TokenTree);
+ fn TokenStream__from_string(str: FFIString, ts: *mut TokenStream) -> bool;
+ fn TokenStream__clone(ts: *const TokenStream) -> TokenStream;
+ fn TokenStream__drop(stream: *mut TokenStream);
+}
+
+#[repr(C)]
+#[derive(Clone)]
+pub enum TokenTree {
+ Group(Group),
+ Ident(Ident),
+ Punct(Punct),
+ Literal(Literal),
+}
+
+impl fmt::Display for TokenTree {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ TokenTree::Group(group) => group.fmt(f),
+ TokenTree::Ident(ident) => ident.fmt(f),
+ TokenTree::Punct(punct) => punct.fmt(f),
+ TokenTree::Literal(literal) => literal.fmt(f),
+ }
+ }
+}
+
+impl From<ExternalTokenTree> for TokenTree {
+ fn from(value: ExternalTokenTree) -> Self {
+ match value {
+ ExternalTokenTree::Group(g) => TokenTree::Group(g.0),
+ ExternalTokenTree::Ident(i) => TokenTree::Ident(i.0),
+ ExternalTokenTree::Punct(p) => TokenTree::Punct(p.0),
+ ExternalTokenTree::Literal(l) => TokenTree::Literal(l.0),
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct TokenStream {
+ pub(crate) data: *const TokenTree,
+ pub(crate) size: u64,
+ capacity: u64,
+}
+
+impl TokenStream {
+ pub fn new() -> Self {
+ unsafe { TokenStream__new() }
+ }
+
+ fn with_capacity(capacity: u64) -> Self {
+ unsafe { TokenStream__with_capacity(capacity) }
+ }
+
+ fn push(&mut self, tree: TokenTree) {
+ unsafe { TokenStream__push(self as *mut TokenStream, tree) }
+ }
+
+ pub fn is_empty(&self) -> bool {
+ 0 == self.size
+ }
+
+ pub fn from_iterator<I>(it: I) -> Self
+ where
+ I: IntoIterator<Item = ExternalTokenStream>,
+ {
+ let it = it.into_iter();
+ let mut result = TokenStream::with_capacity(it.size_hint().0.try_into().unwrap());
+ for stream in it {
+ for item in stream.into_iter() {
+ result.push(item.into());
+ }
+ }
+ result
+ }
+
+ pub fn from_tree_iterator<I>(it: I) -> Self
+ where
+ I: IntoIterator<Item = ExternalTokenTree>,
+ {
+ let it = it.into_iter();
+ let mut result = TokenStream::with_capacity(it.size_hint().0.try_into().unwrap());
+ for item in it {
+ result.push(item.into());
+ }
+ result
+ }
+}
+
+impl Extend<ExternalTokenTree> for TokenStream {
+ fn extend<I: IntoIterator<Item = ExternalTokenTree>>(&mut self, trees: I) {
+ for tt in trees {
+ self.push(tt.into())
+ }
+ }
+}
+
+impl Extend<ExternalTokenStream> for TokenStream {
+ fn extend<I: IntoIterator<Item = ExternalTokenStream>>(&mut self, streams: I) {
+ for stream in streams {
+ for tt in stream {
+ self.push(tt.into());
+ }
+ }
+ }
+}
+
+impl fmt::Display for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ for i in unsafe { slice::from_raw_parts(self.data, self.size.try_into().unwrap()) } {
+ i.fmt(f)?;
+ match i {
+ TokenTree::Punct(_) => (),
+ _ => f.write_str(" ")?,
+ }
+ }
+ Ok(())
+ }
+}
+
+impl FromStr for TokenStream {
+ type Err = LexError;
+ fn from_str(string: &str) -> Result<Self, LexError> {
+ let mut ts = TokenStream::new();
+ if unsafe { TokenStream__from_string(string.into(), &mut ts as *mut TokenStream) } {
+ Err(LexError)
+ } else {
+ Ok(ts)
+ }
+ }
+}
+
+impl Clone for TokenStream {
+ fn clone(&self) -> Self {
+ unsafe { TokenStream__clone(self as *const TokenStream) }
+ }
+}
+
+impl Drop for TokenStream {
+ fn drop(&mut self) {
+ unsafe { TokenStream__drop(self as *mut TokenStream) }
+ }
+}
diff --git a/libgrust/libproc_macro/group.rs b/libgrust/libproc_macro/group.rs
new file mode 100644
index 0000000..29bfb9d
--- /dev/null
+++ b/libgrust/libproc_macro/group.rs
@@ -0,0 +1,88 @@
+use bridge;
+use std::fmt;
+use Span;
+use TokenStream;
+
+/// Describes how a sequence of token trees is delimited.
+#[repr(C)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Delimiter {
+ /// The sequence is delimited by a parenthesis `(...)`.
+ Parenthesis,
+ /// The sequence is delimited by a brace `{...}`.
+ Brace,
+ /// The sequence is delimited by a bracket `[...]`.
+ Bracket,
+ /// Invisible delimiter to preserve operator priority.
+ None,
+}
+
+/// A delimited token stream.
+#[derive(Clone)]
+pub struct Group(pub(crate) bridge::group::Group);
+
+impl Group {
+ /// Creates a new `Group`.
+ ///
+ /// # Arguments
+ ///
+ /// * `delimiter` - The delimiter surrounding the inner [`TokenStream`].
+ /// * `stream` - The tokenstream for this `Group`.
+ pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
+ Group(bridge::group::Group::new(delimiter, stream.0))
+ }
+
+ /// Get the delimiter of the `Group`.
+ pub fn delimiter(&self) -> Delimiter {
+ self.0.delimiter()
+ }
+
+ /// Get the stream of the `Group`.
+ ///
+ /// # Note
+ ///
+ /// The returned stream does not include the delimiters of this group.
+ pub fn stream(&self) -> TokenStream {
+ TokenStream(self.0.stream())
+ }
+
+ /// Get the span for the delimiters of this token stream, spanning the
+ /// entire group.
+ pub fn span(&self) -> Span {
+ Span(self.0.span())
+ }
+
+ /// Get the span pointing to the opening delimiter of this `Group`.
+ pub fn span_open(&self) -> Span {
+ Span(self.0.span())
+ }
+
+ /// Get the span pointing to the closing delimiter of this `Group`.
+ pub fn span_close(&self) -> Span {
+ Span(self.0.span())
+ }
+
+ /// Change the span for this `Group`'s delimiters, but not its internal
+ /// tokens.
+ ///
+ /// # Note
+ ///
+ /// This method will **not** set the span of all the internal tokens spanned
+ /// by this group, but rather it will only set the span of the delimiter
+ /// tokens at the level of the `Group`.
+ pub fn set_span(&mut self, span: Span) {
+ self.0.set_span(span.0)
+ }
+}
+
+impl fmt::Display for Group {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl fmt::Debug for Group {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
diff --git a/libgrust/libproc_macro/ident.rs b/libgrust/libproc_macro/ident.rs
new file mode 100644
index 0000000..809c993
--- /dev/null
+++ b/libgrust/libproc_macro/ident.rs
@@ -0,0 +1,67 @@
+use bridge;
+use std::fmt;
+use Span;
+
+/// An identifier.
+#[derive(Clone)]
+pub struct Ident(pub(crate) bridge::ident::Ident);
+
+impl Ident {
+ /// Creates a new identifier.
+ ///
+ /// # Arguments
+ ///
+ /// * `string` - A valid identifier.
+ /// * `span` - The span of the identifier.
+ ///
+ /// # Panics
+ ///
+ /// The `string` argument must be a valid identifier permitted by the
+ /// language, otherwise the function will panic.
+ pub fn new(string: &str, span: Span) -> Self {
+ Ident(bridge::ident::Ident::new(string, span.0))
+ }
+
+ /// Creates a new raw identifier.
+ ///
+ /// # Arguments
+ ///
+ /// * `string` - A valid identifier.
+ /// * `span` - The span of the identifier.
+ ///
+ /// # Panics
+ ///
+ /// The `string` argument must be a valid identifier permitted by the
+ /// language. Furthermore, it should not be a keyword used in path
+ /// segments, otherwise this function will panic.
+ pub fn new_raw(string: &str, span: Span) -> Self {
+ Ident(bridge::ident::Ident::new_raw(string, span.0))
+ }
+
+ /// Return the span of the identifier
+ pub fn span(&self) -> Span {
+ Span(self.0.span())
+ }
+
+ /// Change the span of the identifier.
+ ///
+ /// # Arguments
+ ///
+ /// * `span` - The new span value.
+ pub fn set_span(&mut self, span: Span) {
+ self.0.set_span(span.0);
+ }
+}
+
+impl fmt::Display for Ident {
+ /// Display as lossless converted string.
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl fmt::Debug for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
diff --git a/libgrust/libproc_macro/lib.rs b/libgrust/libproc_macro/lib.rs
new file mode 100644
index 0000000..a1be0ac
--- /dev/null
+++ b/libgrust/libproc_macro/lib.rs
@@ -0,0 +1,198 @@
+pub use group::{Delimiter, Group};
+pub use ident::Ident;
+pub use literal::Literal;
+pub use punct::{Punct, Spacing};
+pub use span::Span;
+use std::error;
+use std::{fmt, iter, str::FromStr};
+
+mod bridge;
+mod group;
+mod ident;
+mod literal;
+mod punct;
+mod span;
+pub mod token_stream;
+
+/// Determines whether proc_macro has been made accessible to the currently
+/// running program.
+///
+/// # Note
+///
+/// This function provide a non panicking way to detect whether the API is
+/// invoked from inside of a procedural macro.
+pub fn is_available() -> bool {
+ bridge::is_available()
+}
+
+/// A single token or a delimited sequence of token trees.
+#[derive(Clone)]
+pub enum TokenTree {
+ Group(Group),
+ Ident(Ident),
+ Punct(Punct),
+ Literal(Literal),
+}
+
+type InternalTokenTree = bridge::token_stream::TokenTree;
+
+impl From<InternalTokenTree> for TokenTree {
+ fn from(value: InternalTokenTree) -> Self {
+ match value {
+ InternalTokenTree::Group(g) => TokenTree::Group(Group(g)),
+ InternalTokenTree::Ident(i) => TokenTree::Ident(Ident(i)),
+ InternalTokenTree::Punct(p) => TokenTree::Punct(Punct(p)),
+ InternalTokenTree::Literal(l) => TokenTree::Literal(Literal(l)),
+ }
+ }
+}
+
+impl TokenTree {
+ /// Get the [`Span`] for this TokenTree.
+ pub fn span(&self) -> Span {
+ match self {
+ TokenTree::Group(group) => group.span(),
+ TokenTree::Ident(ident) => ident.span(),
+ TokenTree::Punct(punct) => punct.span(),
+ TokenTree::Literal(literal) => literal.span(),
+ }
+ }
+
+ /// Set the span for this TokenTree.
+ ///
+ /// # Arguments
+ ///
+ /// * `span` - The new span value.
+ pub fn set_span(&mut self, span: Span) {
+ match self {
+ TokenTree::Group(group) => group.set_span(span),
+ TokenTree::Ident(ident) => ident.set_span(span),
+ TokenTree::Punct(punct) => punct.set_span(span),
+ TokenTree::Literal(literal) => literal.set_span(span),
+ }
+ }
+}
+
+impl fmt::Debug for TokenTree {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ TokenTree::Group(group) => group.fmt(f),
+ TokenTree::Ident(ident) => ident.fmt(f),
+ TokenTree::Punct(punct) => punct.fmt(f),
+ TokenTree::Literal(literal) => literal.fmt(f),
+ }
+ }
+}
+
+impl fmt::Display for TokenTree {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ TokenTree::Group(group) => group.fmt(f),
+ TokenTree::Ident(ident) => ident.fmt(f),
+ TokenTree::Punct(punct) => punct.fmt(f),
+ TokenTree::Literal(literal) => literal.fmt(f),
+ }
+ }
+}
+
+impl From<Group> for TokenTree {
+ fn from(g: Group) -> Self {
+ TokenTree::Group(g)
+ }
+}
+
+impl From<Ident> for TokenTree {
+ fn from(i: Ident) -> Self {
+ TokenTree::Ident(i)
+ }
+}
+
+impl From<Punct> for TokenTree {
+ fn from(p: Punct) -> Self {
+ TokenTree::Punct(p)
+ }
+}
+
+impl From<Literal> for TokenTree {
+ fn from(l: Literal) -> Self {
+ TokenTree::Literal(l)
+ }
+}
+
+/// Error returned from `from_str` functions.
+#[derive(Debug)]
+pub struct LexError;
+
+impl fmt::Display for LexError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("cannot parse string into token stream")
+ }
+}
+
+impl error::Error for LexError {}
+
+/// An abstract sequence of token trees.
+///
+/// This type provides interfaces for iterating over those token trees. This
+/// is both the input and the output of `#[proc_macro]`,
+/// `#[proc_macro_attribute]` and `#[proc_macro_derive]` definitions.
+#[derive(Clone)]
+pub struct TokenStream(bridge::token_stream::TokenStream);
+
+impl TokenStream {
+ // TODO: Add experimental API functions for this type
+
+ /// Creates an empty `TokenStream` containing no token trees.
+ pub fn new() -> Self {
+ TokenStream(bridge::token_stream::TokenStream::new())
+ }
+
+ /// Checks if this `TokenStream` is empty.
+ pub fn is_empty(&self) -> bool {
+ self.0.is_empty()
+ }
+}
+
+impl fmt::Display for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl fmt::Debug for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl FromStr for TokenStream {
+ type Err = LexError;
+
+ fn from_str(src: &str) -> Result<Self, LexError> {
+ bridge::token_stream::TokenStream::from_str(src).map(TokenStream)
+ }
+}
+
+impl iter::FromIterator<TokenTree> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
+ TokenStream(bridge::token_stream::TokenStream::from_tree_iterator(trees))
+ }
+}
+
+impl iter::FromIterator<TokenStream> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
+ TokenStream(bridge::token_stream::TokenStream::from_iterator(streams))
+ }
+}
+
+impl Extend<TokenTree> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
+ self.0.extend(trees);
+ }
+}
+
+impl Extend<TokenStream> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+ self.0.extend(streams)
+ }
+}
diff --git a/libgrust/libproc_macro/literal.rs b/libgrust/libproc_macro/literal.rs
new file mode 100644
index 0000000..171ca56
--- /dev/null
+++ b/libgrust/libproc_macro/literal.rs
@@ -0,0 +1,189 @@
+use bridge;
+use std::fmt;
+use std::str::FromStr;
+use LexError;
+use Span;
+
+/// A type representing a literal value except `true` and `false`.
+///
+/// This could be one of the following:
+/// * literal string (`"hello"`)
+/// * byte string (`b"hello"`)
+/// * character (`'a'`)
+/// * byte character (`b'a'`)
+/// * unsuffixed integer (`42`)
+/// * suffixed integer (`42u8`)
+/// * unsuffixed floating point number (`1.618`)
+/// * suffixed floating point number (`1.618f32`)
+///
+/// # Note
+///
+/// Boolean literals like `true` and `false` are `Ident`s and do not belong
+/// here.
+#[derive(Clone)]
+pub struct Literal(pub(crate) bridge::literal::Literal);
+
+impl Literal {
+ // TODO: Add experimental API functions for this type
+ // TODO: Generate those constructor with 1/2 macros instead
+
+ pub fn u8_suffixed(n: u8) -> Self {
+ Literal(bridge::literal::Literal::u8_suffixed(n))
+ }
+
+ pub fn u16_suffixed(n: u16) -> Self {
+ Literal(bridge::literal::Literal::u16_suffixed(n))
+ }
+
+ pub fn u32_suffixed(n: u32) -> Self {
+ Literal(bridge::literal::Literal::u32_suffixed(n))
+ }
+
+ pub fn u64_suffixed(n: u64) -> Self {
+ Literal(bridge::literal::Literal::u64_suffixed(n))
+ }
+
+ pub fn u128_suffixed(n: u128) -> Self {
+ Literal(bridge::literal::Literal::u128_suffixed(n))
+ }
+
+ pub fn usize_suffixed(n: usize) -> Self {
+ Literal(bridge::literal::Literal::usize_suffixed(n))
+ }
+
+ pub fn i8_suffixed(n: i8) -> Self {
+ Literal(bridge::literal::Literal::i8_suffixed(n))
+ }
+
+ pub fn i16_suffixed(n: i16) -> Self {
+ Literal(bridge::literal::Literal::i16_suffixed(n))
+ }
+
+ pub fn i32_suffixed(n: i32) -> Self {
+ Literal(bridge::literal::Literal::i32_suffixed(n))
+ }
+
+ pub fn i64_suffixed(n: i64) -> Self {
+ Literal(bridge::literal::Literal::i64_suffixed(n))
+ }
+
+ pub fn i128_suffixed(n: i128) -> Self {
+ Literal(bridge::literal::Literal::i128_suffixed(n))
+ }
+
+ pub fn isize_suffixed(n: isize) -> Self {
+ Literal(bridge::literal::Literal::isize_suffixed(n))
+ }
+
+ // Unsuffixed
+
+ pub fn u8_unsuffixed(n: u8) -> Self {
+ Literal(bridge::literal::Literal::u8_unsuffixed(n))
+ }
+
+ pub fn u16_unsuffixed(n: u16) -> Self {
+ Literal(bridge::literal::Literal::u16_unsuffixed(n))
+ }
+
+ pub fn u32_unsuffixed(n: u32) -> Self {
+ Literal(bridge::literal::Literal::u32_unsuffixed(n))
+ }
+
+ pub fn u64_unsuffixed(n: u64) -> Self {
+ Literal(bridge::literal::Literal::u64_unsuffixed(n))
+ }
+
+ pub fn u128_unsuffixed(n: u128) -> Self {
+ Literal(bridge::literal::Literal::u128_unsuffixed(n))
+ }
+
+ pub fn usize_unsuffixed(n: usize) -> Self {
+ Literal(bridge::literal::Literal::usize_unsuffixed(n))
+ }
+
+ pub fn i8_unsuffixed(n: i8) -> Self {
+ Literal(bridge::literal::Literal::i8_unsuffixed(n))
+ }
+
+ pub fn i16_unsuffixed(n: i16) -> Self {
+ Literal(bridge::literal::Literal::i16_unsuffixed(n))
+ }
+
+ pub fn i32_unsuffixed(n: i32) -> Self {
+ Literal(bridge::literal::Literal::i32_unsuffixed(n))
+ }
+
+ pub fn i64_unsuffixed(n: i64) -> Self {
+ Literal(bridge::literal::Literal::i64_unsuffixed(n))
+ }
+
+ pub fn i128_unsuffixed(n: i128) -> Self {
+ Literal(bridge::literal::Literal::i128_unsuffixed(n))
+ }
+
+ pub fn isize_unsuffixed(n: isize) -> Self {
+ Literal(bridge::literal::Literal::isize_unsuffixed(n))
+ }
+
+ pub fn f32_unsuffixed(n: f32) -> Self {
+ Literal(bridge::literal::Literal::f32_unsuffixed(n))
+ }
+
+ pub fn f32_suffixed(n: f32) -> Self {
+ Literal(bridge::literal::Literal::f32_suffixed(n))
+ }
+
+ pub fn f64_unsuffixed(n: f64) -> Self {
+ Literal(bridge::literal::Literal::f64_unsuffixed(n))
+ }
+
+ pub fn f64_suffixed(n: f64) -> Self {
+ Literal(bridge::literal::Literal::f64_suffixed(n))
+ }
+
+ pub fn string(string: &str) -> Self {
+ Literal(bridge::literal::Literal::string(string))
+ }
+
+ pub fn character(c: char) -> Self {
+ Literal(bridge::literal::Literal::character(c))
+ }
+
+ pub fn byte_string(bytes: &[u8]) -> Self {
+ Literal(bridge::literal::Literal::byte_string(bytes))
+ }
+
+ /// Get the [`Span`] for this literal.
+ pub fn span(&self) -> Span {
+ Span(self.0.span())
+ }
+
+ /// Set the span for this literal.
+ ///
+ /// # Arguments
+ ///
+ /// * `span` - The new span value.
+ pub fn set_span(&mut self, span: Span) {
+ self.0.set_span(span.0);
+ }
+}
+
+impl fmt::Debug for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl fmt::Display for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl FromStr for Literal {
+ type Err = LexError;
+
+ fn from_str(src: &str) -> Result<Self, LexError> {
+ bridge::literal::Literal::from_str(src).map(Literal)
+ }
+}
diff --git a/libgrust/libproc_macro/punct.rs b/libgrust/libproc_macro/punct.rs
new file mode 100644
index 0000000..0f7830e
--- /dev/null
+++ b/libgrust/libproc_macro/punct.rs
@@ -0,0 +1,92 @@
+use bridge;
+use std::convert::TryInto;
+use std::fmt;
+use Span;
+
+/// Describes the context of a [`Punct`] relatively to the next token.
+#[repr(C)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Spacing {
+ /// A [`Punct`] is not immediately followed by another `Punct`.
+ Alone,
+ /// A [`Punct`] is immediately followed by another `Punct` and can be
+ /// combined into a multi-character operator.
+ Joint,
+}
+
+/// Single punctuation character such as `+`, `-` or `#`.
+///
+/// Multi-character operators like `+=` are represented as two instances of
+/// `Punct` with different forms of `Spacing` returned.
+#[derive(Clone)]
+pub struct Punct(pub(crate) bridge::punct::Punct);
+
+impl Punct {
+ /// Creates a new `Punct` from a given character and spacing.
+ ///
+ /// # Arguments
+ ///
+ /// * `ch` - The punctuation character.
+ /// * `spacing` - The link between this character and the next one.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if the `ch` argument is not a valid
+ /// punctuation character allowed by the language.
+ pub fn new(ch: char, spacing: Spacing) -> Self {
+ Punct(bridge::punct::Punct::new(ch, spacing))
+ }
+
+ /// Get the value for this punctuation character as `char`.
+ pub fn as_char(&self) -> char {
+ self.0
+ .ch
+ .try_into()
+ .expect("Cannot convert from u32 to char")
+ }
+
+ /// Get the [`Spacing`] of this punctuation character, indicating whether
+ /// the following character can be combined into a multi-character operator
+ /// or not.
+ pub fn spacing(&self) -> Spacing {
+ self.0.spacing
+ }
+
+ /// Get the [`Span`] for this punctuation character.
+ pub fn span(&self) -> Span {
+ Span(self.0.span())
+ }
+
+ /// Set the span for this punctuation character.
+ ///
+ /// # Arguments
+ ///
+ /// * `span` - The new span value.
+ pub fn set_span(&mut self, span: Span) {
+ self.0.set_span(span.0);
+ }
+}
+
+impl fmt::Display for Punct {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl fmt::Debug for Punct {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl PartialEq<char> for Punct {
+ fn eq(&self, rhs: &char) -> bool {
+ self.as_char() == *rhs
+ }
+}
+
+impl PartialEq<Punct> for char {
+ fn eq(&self, rhs: &Punct) -> bool {
+ *self == rhs.as_char()
+ }
+}
diff --git a/libgrust/libproc_macro/span.rs b/libgrust/libproc_macro/span.rs
new file mode 100644
index 0000000..b5d573c
--- /dev/null
+++ b/libgrust/libproc_macro/span.rs
@@ -0,0 +1,52 @@
+use bridge;
+use std::fmt;
+
+/// A region of source code along with macro expansion information.
+#[derive(Copy, Clone)]
+pub struct Span(pub(crate) bridge::span::Span);
+
+impl Span {
+ // TODO: Add experimental API functions for this type
+
+ /// Creates a new span that resolves at the macro call location.
+ pub fn call_site() -> Self {
+ Span(bridge::span::Span::call_site())
+ }
+
+ /// Creates a new span that resolved sometimes at macro call site, and
+ /// sometimes at macro definition site.
+ pub fn mixed_site() -> Self {
+ Span(bridge::span::Span::mixed_site())
+ }
+
+ /// Creates a new span with the same line/column informations but that
+ /// resolve symbols as though it were at `other`.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - Other span to resolve at.
+ pub fn resolved_at(&self, other: Span) -> Self {
+ Span(self.0.resolved_at(other.0))
+ }
+
+ /// Creates a new span with the same name resolution behavior as self, but
+ /// with the line/column information of `other`.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - Other span containing the line/column informations to use.
+ pub fn located_at(&self, other: Span) -> Self {
+ Span(self.0.located_at(other.0))
+ }
+
+ /// Return the source text behind a span.
+ pub fn source_text(&self) -> Option<String> {
+ self.0.source_text()
+ }
+}
+
+impl fmt::Debug for Span {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
diff --git a/libgrust/libproc_macro/token_stream.rs b/libgrust/libproc_macro/token_stream.rs
new file mode 100644
index 0000000..9333e3e
--- /dev/null
+++ b/libgrust/libproc_macro/token_stream.rs
@@ -0,0 +1,52 @@
+//! Public implementation details for the `TokenStream` type, such as iterators.
+use bridge;
+use std::convert::TryInto;
+
+use TokenStream;
+use TokenTree;
+
+/// An iterator over [`TokenStream`]'s [`TokenTree`]s.
+#[derive(Clone)]
+pub struct IntoIter {
+ current: *const bridge::token_stream::TokenTree,
+ end: *const bridge::token_stream::TokenTree,
+}
+
+impl Iterator for IntoIter {
+ type Item = TokenTree;
+
+ fn next(&mut self) -> Option<TokenTree> {
+ if self.current == self.end {
+ None
+ } else {
+ let result = self.current;
+ self.current = unsafe { self.current.add(1) };
+ Some(unsafe { std::ptr::read(result) }.into())
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ // TODO: I'm not a fan of those casts, once #![feature(ptr_sub_ptr)]
+ // is implemented we may replace this line by the following:
+ // self.end.sub_ptr(self.current)
+ let remaining = self.end as usize - self.current as usize;
+ (remaining, Some(remaining))
+ }
+
+ fn count(self) -> usize {
+ self.end as usize - self.current as usize
+ }
+}
+
+impl IntoIterator for TokenStream {
+ type Item = TokenTree;
+ type IntoIter = IntoIter;
+
+ fn into_iter(self) -> IntoIter {
+ let capacity = self.0.size.try_into().unwrap();
+ IntoIter {
+ current: self.0.data,
+ end: unsafe { self.0.data.add(capacity) },
+ }
+ }
+}