use std::marker::PhantomData;
use std::sync::atomic::AtomicU32;
#[repr(C)]
pub struct Buffer {
pub data: *mut u8,
pub len: usize,
pub capacity: usize,
pub reserve: Option<extern "C" fn(Buffer, usize) -> Buffer>,
pub drop: Option<extern "C" fn(Buffer)>,
}
impl Buffer {
pub fn as_slice(&self) -> &[u8] {
if self.data.is_null() || self.len == 0 {
&[]
} else {
unsafe { std::slice::from_raw_parts(self.data, self.len) }
}
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
if self.data.is_null() || self.len == 0 {
&mut []
} else {
unsafe { std::slice::from_raw_parts_mut(self.data, self.len) }
}
}
pub fn from_vec(data: Vec<u8>) -> Self {
let mut v = std::mem::ManuallyDrop::new(data);
Buffer {
data: v.as_mut_ptr(),
len: v.len(),
capacity: v.capacity(),
reserve: Some(buffer_reserve),
drop: Some(buffer_drop),
}
}
}
extern "C" fn buffer_drop(b: Buffer) {
if !b.data.is_null() && b.capacity > 0 {
unsafe {
drop(Vec::from_raw_parts(b.data, b.len, b.capacity));
}
}
}
extern "C" fn buffer_reserve(b: Buffer, additional: usize) -> Buffer {
let mut v = if !b.data.is_null() && b.capacity > 0 {
unsafe { Vec::from_raw_parts(b.data, b.len, b.capacity) }
} else {
Vec::new()
};
v.reserve(additional);
Buffer::from_vec(v)
}
#[repr(C)]
pub struct Closure<'a, A, R> {
pub call: unsafe extern "C" fn(*mut u8, A) -> R,
pub env: *mut u8,
pub _marker: PhantomData<&'a mut ()>,
}
#[repr(C)]
pub struct HandleCounters {
pub free_functions: AtomicU32,
pub token_stream: AtomicU32,
pub source_file: AtomicU32,
pub span: AtomicU32,
}
#[repr(C)]
pub struct BridgeConfig<'a> {
pub input: Buffer,
pub dispatch: Closure<'a, Buffer, Buffer>,
pub force_show_panics: bool,
pub _marker: PhantomData<&'a ()>,
}
#[repr(C)]
pub struct Client<I, O> {
pub handle_counters: &'static HandleCounters,
pub run: extern "C" fn(BridgeConfig<'_>) -> Buffer,
pub _marker: PhantomData<fn(I) -> O>,
}
impl<I, O> Clone for Client<I, O> {
fn clone(&self) -> Self {
*self
}
}
impl<I, O> Copy for Client<I, O> {}
#[repr(C)]
pub struct TokenStream {
_private: [u8; 0],
}
#[repr(C)]
pub enum ProcMacro {
CustomDerive {
trait_name: &'static str,
attributes: &'static [&'static str],
client: Client<TokenStream, TokenStream>,
},
Attr {
name: &'static str,
client: Client<(TokenStream, TokenStream), TokenStream>,
},
Bang {
name: &'static str,
client: Client<TokenStream, TokenStream>,
},
}
impl ProcMacro {
pub fn name(&self) -> &'static str {
match self {
ProcMacro::CustomDerive { trait_name, .. } => trait_name,
ProcMacro::Attr { name, .. } => name,
ProcMacro::Bang { name, .. } => name,
}
}
pub fn kind(&self) -> &'static str {
match self {
ProcMacro::CustomDerive { .. } => "CustomDerive",
ProcMacro::Attr { .. } => "Attr",
ProcMacro::Bang { .. } => "Bang",
}
}
}