-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Proc macro tweaks #97004
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proc macro tweaks #97004
Changes from all commits
2469ed0
a61a85e
e02789c
2ece157
1a9514d
dbdc7dd
bc70d0d
9a785e0
c2c5057
f5c9c12
e6fa19a
41c10dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,37 +6,37 @@ use std::ops::{Deref, DerefMut}; | |
use std::slice; | ||
|
||
#[repr(C)] | ||
pub struct Buffer<T: Copy> { | ||
data: *mut T, | ||
pub struct Buffer { | ||
data: *mut u8, | ||
Comment on lines
-9
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the record, I think the reason I made this generic was to avoid accidentally doing the wrong thing because the types happened to match up (especially since there's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would any type other than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's not what I meant, but rather that writing parametric code can sometimes help avoid making mistakes (which can be catastrophic in It doesn't make sense at all from the perspective of whether e.g. a C++ container might be templated or not, but in does in Rust because of the type-checking in the generic form. Anyway it doesn't matter much, I was just explaining that Hopefully we can remove this |
||
len: usize, | ||
capacity: usize, | ||
reserve: extern "C" fn(Buffer<T>, usize) -> Buffer<T>, | ||
drop: extern "C" fn(Buffer<T>), | ||
reserve: extern "C" fn(Buffer, usize) -> Buffer, | ||
drop: extern "C" fn(Buffer), | ||
} | ||
|
||
unsafe impl<T: Copy + Sync> Sync for Buffer<T> {} | ||
unsafe impl<T: Copy + Send> Send for Buffer<T> {} | ||
unsafe impl Sync for Buffer {} | ||
unsafe impl Send for Buffer {} | ||
|
||
impl<T: Copy> Default for Buffer<T> { | ||
impl Default for Buffer { | ||
fn default() -> Self { | ||
Self::from(vec![]) | ||
} | ||
} | ||
|
||
impl<T: Copy> Deref for Buffer<T> { | ||
type Target = [T]; | ||
fn deref(&self) -> &[T] { | ||
unsafe { slice::from_raw_parts(self.data as *const T, self.len) } | ||
impl Deref for Buffer { | ||
type Target = [u8]; | ||
fn deref(&self) -> &[u8] { | ||
unsafe { slice::from_raw_parts(self.data as *const u8, self.len) } | ||
} | ||
} | ||
|
||
impl<T: Copy> DerefMut for Buffer<T> { | ||
fn deref_mut(&mut self) -> &mut [T] { | ||
impl DerefMut for Buffer { | ||
fn deref_mut(&mut self) -> &mut [u8] { | ||
unsafe { slice::from_raw_parts_mut(self.data, self.len) } | ||
} | ||
} | ||
|
||
impl<T: Copy> Buffer<T> { | ||
impl Buffer { | ||
pub(super) fn new() -> Self { | ||
Self::default() | ||
} | ||
|
@@ -53,7 +53,7 @@ impl<T: Copy> Buffer<T> { | |
// because in the case of small arrays, codegen can be more efficient | ||
// (avoiding a memmove call). With extend_from_slice, LLVM at least | ||
// currently is not able to make that optimization. | ||
pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[T; N]) { | ||
pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[u8; N]) { | ||
if xs.len() > (self.capacity - self.len) { | ||
let b = self.take(); | ||
*self = (b.reserve)(b, xs.len()); | ||
|
@@ -64,7 +64,7 @@ impl<T: Copy> Buffer<T> { | |
} | ||
} | ||
|
||
pub(super) fn extend_from_slice(&mut self, xs: &[T]) { | ||
pub(super) fn extend_from_slice(&mut self, xs: &[u8]) { | ||
if xs.len() > (self.capacity - self.len) { | ||
let b = self.take(); | ||
*self = (b.reserve)(b, xs.len()); | ||
|
@@ -75,7 +75,7 @@ impl<T: Copy> Buffer<T> { | |
} | ||
} | ||
|
||
pub(super) fn push(&mut self, v: T) { | ||
pub(super) fn push(&mut self, v: u8) { | ||
// 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. | ||
|
@@ -90,7 +90,7 @@ impl<T: Copy> Buffer<T> { | |
} | ||
} | ||
|
||
impl Write for Buffer<u8> { | ||
impl Write for Buffer { | ||
fn write(&mut self, xs: &[u8]) -> io::Result<usize> { | ||
self.extend_from_slice(xs); | ||
Ok(xs.len()) | ||
|
@@ -106,35 +106,35 @@ impl Write for Buffer<u8> { | |
} | ||
} | ||
|
||
impl<T: Copy> Drop for Buffer<T> { | ||
impl Drop for Buffer { | ||
fn drop(&mut self) { | ||
let b = self.take(); | ||
(b.drop)(b); | ||
} | ||
} | ||
|
||
impl<T: Copy> From<Vec<T>> for Buffer<T> { | ||
fn from(mut v: Vec<T>) -> Self { | ||
impl From<Vec<u8>> for Buffer { | ||
fn from(mut v: Vec<u8>) -> Self { | ||
let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity()); | ||
mem::forget(v); | ||
|
||
// This utility function is nested in here because it can *only* | ||
// be safely called on `Buffer`s created by *this* `proc_macro`. | ||
fn to_vec<T: Copy>(b: Buffer<T>) -> Vec<T> { | ||
fn to_vec(b: Buffer) -> Vec<u8> { | ||
unsafe { | ||
let Buffer { data, len, capacity, .. } = b; | ||
mem::forget(b); | ||
Vec::from_raw_parts(data, len, capacity) | ||
} | ||
} | ||
|
||
extern "C" fn reserve<T: Copy>(b: Buffer<T>, additional: usize) -> Buffer<T> { | ||
extern "C" fn reserve(b: Buffer, additional: usize) -> Buffer { | ||
let mut v = to_vec(b); | ||
v.reserve(additional); | ||
Buffer::from(v) | ||
} | ||
|
||
extern "C" fn drop<T: Copy>(b: Buffer<T>) { | ||
extern "C" fn drop(b: Buffer) { | ||
mem::drop(to_vec(b)); | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.