summaryrefslogtreecommitdiff
path: root/serde_v8/magic/v8slice.rs
diff options
context:
space:
mode:
Diffstat (limited to 'serde_v8/magic/v8slice.rs')
-rw-r--r--serde_v8/magic/v8slice.rs51
1 files changed, 51 insertions, 0 deletions
diff --git a/serde_v8/magic/v8slice.rs b/serde_v8/magic/v8slice.rs
index 6950e29d9..452c857a3 100644
--- a/serde_v8/magic/v8slice.rs
+++ b/serde_v8/magic/v8slice.rs
@@ -3,7 +3,9 @@
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Range;
+use std::rc::Rc;
+use super::rawbytes;
use super::transl8::FromV8;
/// A V8Slice encapsulates a slice that's been borrowed from a JavaScript
@@ -117,3 +119,52 @@ impl AsMut<[u8]> for V8Slice {
self.as_slice_mut()
}
}
+
+// Implement V8Slice -> bytes::Bytes
+impl V8Slice {
+ fn rc_into_byte_parts(self: Rc<Self>) -> (*const u8, usize, *mut V8Slice) {
+ let (ptr, len) = {
+ let slice = self.as_ref();
+ (slice.as_ptr(), slice.len())
+ };
+ let rc_raw = Rc::into_raw(self);
+ let data = rc_raw as *mut V8Slice;
+ (ptr, len, data)
+ }
+}
+
+impl From<V8Slice> for bytes::Bytes {
+ fn from(v8slice: V8Slice) -> Self {
+ let (ptr, len, data) = Rc::new(v8slice).rc_into_byte_parts();
+ rawbytes::RawBytes::new_raw(ptr, len, data.cast(), &V8SLICE_VTABLE)
+ }
+}
+
+// NOTE: in the limit we could avoid extra-indirection and use the C++ shared_ptr
+// but we can't store both the underlying data ptr & ctrl ptr ... so instead we
+// use a shared rust ptr (Rc/Arc) that itself controls the C++ shared_ptr
+const V8SLICE_VTABLE: rawbytes::Vtable = rawbytes::Vtable {
+ clone: v8slice_clone,
+ drop: v8slice_drop,
+};
+
+unsafe fn v8slice_clone(
+ data: &rawbytes::AtomicPtr<()>,
+ ptr: *const u8,
+ len: usize,
+) -> bytes::Bytes {
+ let rc = Rc::from_raw(*data as *const V8Slice);
+ let (_, _, data) = rc.clone().rc_into_byte_parts();
+ std::mem::forget(rc);
+ // NOTE: `bytes::Bytes` does bounds checking so we trust its ptr, len inputs
+ // and must use them to allow cloning Bytes it has sliced
+ rawbytes::RawBytes::new_raw(ptr, len, data.cast(), &V8SLICE_VTABLE)
+}
+
+unsafe fn v8slice_drop(
+ data: &mut rawbytes::AtomicPtr<()>,
+ _: *const u8,
+ _: usize,
+) {
+ drop(Rc::from_raw(*data as *const V8Slice))
+}