pub mod comment_store;
pub mod item_store;
pub mod set_span;
pub mod traverse;
pub use c2rust_ast_printer::pprust::BytePos;
use proc_macro2::Span;
use std::sync::atomic::{AtomicU32, Ordering};
static SPAN_LIMIT: AtomicU32 = AtomicU32::new(0);
fn raise_span_limit(_new_limit: u32) {
let limit = SPAN_LIMIT.load(Ordering::Relaxed);
let new_limit = 0x2000000;
if new_limit >= limit {
let delta = new_limit - limit;
let s = str::repeat(" ", (delta as usize + 7) / 8);
use std::str::FromStr;
let _ = proc_macro2::TokenStream::from_str(&s);
SPAN_LIMIT.store(new_limit, Ordering::Relaxed);
}
}
pub fn pos_to_span(pos: BytePos) -> Span {
SpanExt::new(pos.0, pos.0)
}
pub trait SpanExt: Sized {
fn is_dummy(&self) -> bool;
fn dummy() -> Self;
fn eq(&self, other: &Self) -> bool;
fn new(lo: u32, hi: u32) -> Self;
fn inner(&self) -> (u32, u32);
#[inline(always)]
fn lo(&self) -> BytePos {
BytePos(self.inner().0)
}
#[inline(always)]
fn hi(&self) -> BytePos {
BytePos(self.inner().1)
}
#[inline(always)]
fn with_lo(&self, lo: BytePos) -> Self {
SpanExt::new(lo.0, self.hi().0)
}
#[inline(always)]
fn with_hi(&self, hi: BytePos) -> Self {
SpanExt::new(self.lo().0, hi.0)
}
#[inline(always)]
fn shrink_to_lo(&self) -> Self {
SpanExt::new(self.lo().0, self.lo().0)
}
#[inline(always)]
fn shrink_to_hi(&self) -> Self {
SpanExt::new(self.hi().0, self.hi().0)
}
#[inline(always)]
fn between(&self, end: Self) -> Self {
SpanExt::new(self.hi().0, end.lo().0)
}
fn substitute_dummy(self, other: Self) -> Self {
if self.is_dummy() {
other
} else {
self
}
}
}
#[repr(C)]
struct SpanRepr {
compiler_or_fallback: u32,
lo: u32,
hi: u32,
}
#[cfg_attr(test, test)]
fn validate_repr() {
let repr: SpanRepr = unsafe { std::mem::transmute(Span::call_site()) };
assert!(repr.compiler_or_fallback == 1);
assert!(repr.lo == 0);
assert!(repr.hi == 0);
}
fn get_inner(s: &Span) -> (u32, u32) {
validate_repr();
let repr: &SpanRepr = unsafe { std::mem::transmute(s) };
(repr.lo & 0xffffff, repr.hi & 0xffffff)
}
fn synthesize(lo: u32, hi: u32) -> Span {
raise_span_limit(hi);
validate_repr();
let repr = SpanRepr {
compiler_or_fallback: 1,
lo: lo | 0x1000000,
hi: hi | 0x1000000,
};
unsafe { std::mem::transmute(repr) }
}
impl SpanExt for Span {
fn is_dummy(&self) -> bool {
self.eq(&Self::dummy())
}
fn dummy() -> Self {
Span::call_site()
}
fn eq(&self, other: &Self) -> bool {
get_inner(self) == get_inner(other)
}
fn new(lo: u32, hi: u32) -> Self {
synthesize(lo, hi)
}
fn inner(&self) -> (u32, u32) {
get_inner(self)
}
}