Skip to content

Commit

Permalink
Fix proc macro ffi for #85390
Browse files Browse the repository at this point in the history
  • Loading branch information
yotamofek committed Jun 11, 2021
1 parent fabf47f commit aeb7b18
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions crates/proc_macro_srv/src/proc_macro/bridge/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct Buffer<T: Copy> {
data: *mut T,
len: usize,
capacity: usize,
extend_from_slice: extern "C" fn(Buffer<T>, Slice<'_, T>) -> Buffer<T>,
reserve: extern "C" fn(Buffer<T>, usize) -> Buffer<T>,
drop: extern "C" fn(Buffer<T>),
}

Expand Down Expand Up @@ -82,17 +82,28 @@ impl<T: Copy> Buffer<T> {
}

pub(super) fn extend_from_slice(&mut self, xs: &[T]) {
// Fast path to avoid going through an FFI call.
if let Some(final_len) = self.len.checked_add(xs.len()) {
if final_len <= self.capacity {
let dst = unsafe { slice::from_raw_parts_mut(self.data, self.capacity) };
dst[self.len..][..xs.len()].copy_from_slice(xs);
self.len = final_len;
return;
}
if xs.len() > self.capacity.wrapping_sub(self.len) {
let b = self.take();
*self = (b.reserve)(b, xs.len());
}
unsafe {
xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
self.len += xs.len();
}
}

pub(super) fn push(&mut self, v: T) {
// The code here is taken from Vec::push, and we know that reserve()
// will panic if we're exceeding isize::MAX bytes and so there's no need
// to check for overflow.
if self.len == self.capacity {
let b = self.take();
*self = (b.reserve)(b, 1);
}
unsafe {
*self.data.add(self.len) = v;
self.len += 1;
}
let b = self.take();
*self = (b.extend_from_slice)(b, Slice::from(xs));
}
}

Expand Down Expand Up @@ -134,16 +145,16 @@ impl<T: Copy> From<Vec<T>> for Buffer<T> {
}
}

extern "C" fn extend_from_slice<T: Copy>(b: Buffer<T>, xs: Slice<'_, T>) -> Buffer<T> {
extern "C" fn reserve<T: Copy>(b: Buffer<T>, additional: usize) -> Buffer<T> {
let mut v = to_vec(b);
v.extend_from_slice(&xs);
v.reserve(additional);
Buffer::from(v)
}

extern "C" fn drop<T: Copy>(b: Buffer<T>) {
mem::drop(to_vec(b));
}

Buffer { data, len, capacity, extend_from_slice, drop }
Buffer { data, len, capacity, reserve, drop }
}
}

0 comments on commit aeb7b18

Please sign in to comment.