about summary refs log tree commit diff
path: root/src/libproc_macro/bridge/buffer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libproc_macro/bridge/buffer.rs')
-rw-r--r--src/libproc_macro/bridge/buffer.rs170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/libproc_macro/bridge/buffer.rs b/src/libproc_macro/bridge/buffer.rs
new file mode 100644
index 00000000000..f228841c1e8
--- /dev/null
+++ b/src/libproc_macro/bridge/buffer.rs
@@ -0,0 +1,170 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Buffer management for same-process client<->server communication.
+
+use std::io::{self, Write};
+use std::mem;
+use std::ops::{Deref, DerefMut};
+use std::slice;
+
+#[repr(C)]
+struct Slice<'a, T: 'a> {
+    data: &'a [T; 0],
+    len: usize,
+}
+
+unsafe impl<'a, T: Sync> Sync for Slice<'a, T> {}
+unsafe impl<'a, T: Sync> Send for Slice<'a, T> {}
+
+impl<T> Copy for Slice<'a, T> {}
+impl<T> Clone for Slice<'a, T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<T> From<&'a [T]> for Slice<'a, T> {
+    fn from(xs: &'a [T]) -> Self {
+        Slice {
+            data: unsafe { &*(xs.as_ptr() as *const [T; 0]) },
+            len: xs.len(),
+        }
+    }
+}
+
+impl<T> Deref for Slice<'a, T> {
+    type Target = [T];
+    fn deref(&self) -> &[T] {
+        unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) }
+    }
+}
+
+#[repr(C)]
+pub struct Buffer<T: Copy> {
+    data: *mut T,
+    len: usize,
+    capacity: usize,
+    extend_from_slice: extern "C" fn(Buffer<T>, Slice<T>) -> Buffer<T>,
+    drop: extern "C" fn(Buffer<T>),
+}
+
+unsafe impl<T: Copy + Sync> Sync for Buffer<T> {}
+unsafe impl<T: Copy + Send> Send for Buffer<T> {}
+
+impl<T: Copy> Default for Buffer<T> {
+    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<T: Copy> DerefMut for Buffer<T> {
+    fn deref_mut(&mut self) -> &mut [T] {
+        unsafe { slice::from_raw_parts_mut(self.data, self.len) }
+    }
+}
+
+impl<T: Copy> Buffer<T> {
+    pub(super) fn new() -> Self {
+        Self::default()
+    }
+
+    pub(super) fn clear(&mut self) {
+        self.len = 0;
+    }
+
+    pub(super) fn take(&mut self) -> Self {
+        mem::replace(self, Self::default())
+    }
+
+    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;
+            }
+        }
+        let b = self.take();
+        *self = (b.extend_from_slice)(b, Slice::from(xs));
+    }
+}
+
+impl Write for Buffer<u8> {
+    fn write(&mut self, xs: &[u8]) -> io::Result<usize> {
+        self.extend_from_slice(xs);
+        Ok(xs.len())
+    }
+
+    fn write_all(&mut self, xs: &[u8]) -> io::Result<()> {
+        self.extend_from_slice(xs);
+        Ok(())
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl<T: Copy> Drop for Buffer<T> {
+    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 {
+        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> {
+            unsafe {
+                let Buffer {
+                    data,
+                    len,
+                    capacity,
+                    ..
+                } = b;
+                mem::forget(b);
+                Vec::from_raw_parts(data, len, capacity)
+            }
+        }
+
+        extern "C" fn extend_from_slice<T: Copy>(b: Buffer<T>, xs: Slice<T>) -> Buffer<T> {
+            let mut v = to_vec(b);
+            v.extend_from_slice(&xs);
+            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,
+        }
+    }
+}