diff options
author | Aaron O'Mullan <aaron.omullan@gmail.com> | 2022-05-13 12:53:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-13 12:53:13 +0200 |
commit | 67e5a850cc9b37b76638cfbac9dee08286a3469a (patch) | |
tree | 6e8f3f93ba54f572173fb9d0fb588173157c941c /serde_v8/magic/rawbytes.rs | |
parent | 3e7afb8918fd0f6cedf839a7ebaae6aaee5e66ad (diff) |
feat(serde_v8): bytes::Bytes support (#14412)
Diffstat (limited to 'serde_v8/magic/rawbytes.rs')
-rw-r--r-- | serde_v8/magic/rawbytes.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/serde_v8/magic/rawbytes.rs b/serde_v8/magic/rawbytes.rs new file mode 100644 index 000000000..d82e68717 --- /dev/null +++ b/serde_v8/magic/rawbytes.rs @@ -0,0 +1,96 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. +pub(crate) type AtomicPtr<T> = *mut T; +#[allow(unused)] +pub(crate) struct RawBytes { + ptr: *const u8, + len: usize, + // inlined "trait object" + data: AtomicPtr<()>, + vtable: &'static Vtable, +} + +impl RawBytes { + pub fn new_raw( + ptr: *const u8, + len: usize, + data: AtomicPtr<()>, + vtable: &'static Vtable, + ) -> bytes::Bytes { + RawBytes { + ptr, + len, + data, + vtable, + } + .into() + } +} + +#[allow(unused)] +pub(crate) struct Vtable { + /// fn(data, ptr, len) + pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> bytes::Bytes, + /// fn(data, ptr, len) + pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize), +} + +impl From<RawBytes> for bytes::Bytes { + fn from(b: RawBytes) -> Self { + // SAFETY: RawBytes has the same layout as bytes::Bytes + // this is tested below, both are composed of usize-d ptrs/values + // thus aren't currently subject to rust's field re-ordering to minimize padding + unsafe { std::mem::transmute(b) } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::mem; + + const HELLO: &str = "hello"; + + // ===== impl StaticVtable ===== + + const STATIC_VTABLE: Vtable = Vtable { + clone: static_clone, + drop: static_drop, + }; + + unsafe fn static_clone( + _: &AtomicPtr<()>, + ptr: *const u8, + len: usize, + ) -> bytes::Bytes { + from_static(std::slice::from_raw_parts(ptr, len)).into() + } + + unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) { + // nothing to drop for &'static [u8] + } + + fn from_static(bytes: &'static [u8]) -> RawBytes { + RawBytes { + ptr: bytes.as_ptr(), + len: bytes.len(), + data: std::ptr::null_mut(), + vtable: &STATIC_VTABLE, + } + } + + #[test] + fn bytes_identity() { + let b1: bytes::Bytes = from_static(HELLO.as_bytes()).into(); + let b2 = bytes::Bytes::from_static(HELLO.as_bytes()); + assert_eq!(b1, b2); // Values are equal + } + + #[test] + fn bytes_layout() { + let u1: [usize; 4] = + unsafe { mem::transmute(from_static(HELLO.as_bytes())) }; + let u2: [usize; 4] = + unsafe { mem::transmute(bytes::Bytes::from_static(HELLO.as_bytes())) }; + assert_eq!(u1[..3], u2[..3]); // Struct bytes are equal besides Vtables + } +} |