1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use crate::ArrayBuffer;
use crate::ArrayBufferView;
use crate::BackingStore;
use crate::Local;
use crate::SharedRef;
use crate::binding::memory_span_t;
use crate::scope::PinScope;
use crate::support::int;
use std::convert::TryInto;
use std::ffi::c_void;
use std::mem::MaybeUninit;
unsafe extern "C" {
fn v8__ArrayBufferView__Buffer(
this: *const ArrayBufferView,
) -> *const ArrayBuffer;
fn v8__ArrayBufferView__Buffer__Data(
this: *const ArrayBufferView,
) -> *mut c_void;
fn v8__ArrayBufferView__ByteLength(this: *const ArrayBufferView) -> usize;
fn v8__ArrayBufferView__ByteOffset(this: *const ArrayBufferView) -> usize;
fn v8__ArrayBufferView__HasBuffer(this: *const ArrayBufferView) -> bool;
fn v8__ArrayBufferView__CopyContents(
this: *const ArrayBufferView,
dest: *mut c_void,
byte_length: int,
) -> usize;
fn v8__ArrayBufferView__GetContents(
this: *const ArrayBufferView,
storage: memory_span_t,
) -> memory_span_t;
}
impl ArrayBufferView {
/// Returns underlying ArrayBuffer.
#[inline(always)]
pub fn buffer<'s>(
&self,
scope: &PinScope<'s, '_, ()>,
) -> Option<Local<'s, ArrayBuffer>> {
unsafe { scope.cast_local(|_| v8__ArrayBufferView__Buffer(self)) }
}
/// Returns true if ArrayBufferView's backing ArrayBuffer has already been allocated.
pub fn has_buffer(&self) -> bool {
unsafe { v8__ArrayBufferView__HasBuffer(self) }
}
/// Get a shared pointer to the backing store of this array buffer. This
/// pointer coordinates the lifetime management of the internal storage
/// with any live ArrayBuffers on the heap, even across isolates. The embedder
/// should not attempt to manage lifetime of the storage through other means.
#[inline(always)]
pub fn get_backing_store(&self) -> Option<SharedRef<BackingStore>> {
let buffer = unsafe { v8__ArrayBufferView__Buffer(self) };
unsafe { buffer.as_ref().map(|buffer| buffer.get_backing_store()) }
}
/// Returns the underlying storage for this `ArrayBufferView`, including the built-in `byte_offset`.
/// This is a more efficient way of calling `buffer(scope)->data()`, and may be called without a
/// scope.
#[inline(always)]
pub fn data(&self) -> *mut c_void {
unsafe {
v8__ArrayBufferView__Buffer__Data(self)
.add(v8__ArrayBufferView__ByteOffset(self))
}
}
/// Size of a view in bytes.
#[inline(always)]
pub fn byte_length(&self) -> usize {
unsafe { v8__ArrayBufferView__ByteLength(self) }
}
/// Byte offset in |Buffer|.
#[inline(always)]
pub fn byte_offset(&self) -> usize {
unsafe { v8__ArrayBufferView__ByteOffset(self) }
}
/// Copy the contents of the ArrayBufferView's buffer to an embedder defined
/// memory without additional overhead that calling ArrayBufferView::Buffer
/// might incur.
/// Returns the number of bytes actually written.
#[inline(always)]
pub fn copy_contents(&self, dest: &mut [u8]) -> usize {
unsafe {
v8__ArrayBufferView__CopyContents(
self,
dest.as_mut_ptr() as *mut c_void,
dest.len().try_into().unwrap(),
)
}
}
/// Copy the contents of the ArrayBufferView's buffer to an embedder defined
/// memory without additional overhead that calling ArrayBufferView::Buffer
/// might incur.
/// Returns the number of bytes actually written.
#[inline(always)]
pub fn copy_contents_uninit(&self, dest: &mut [MaybeUninit<u8>]) -> usize {
unsafe {
v8__ArrayBufferView__CopyContents(
self,
dest.as_mut_ptr() as *mut c_void,
dest.len().try_into().unwrap(),
)
}
}
/// Returns the contents of the ArrayBufferView's buffer as a MemorySpan. If
/// the contents are on the V8 heap, they get copied into `storage`. Otherwise
/// a view into the off-heap backing store is returned. The provided storage
/// should be at least as large as the maximum on-heap size of a TypedArray,
/// which is available as `v8::TYPED_ARRAY_MAX_SIZE_IN_HEAP`.
#[inline(always)]
pub unsafe fn get_contents_raw_parts(
&self,
storage: &mut [u8],
) -> (*mut u8, usize) {
unsafe {
let span = v8__ArrayBufferView__GetContents(
self,
memory_span_t {
data: storage.as_mut_ptr(),
size: storage.len(),
},
);
(span.data, span.size)
}
}
/// Returns the contents of the ArrayBufferView's buffer as a MemorySpan. If
/// the contents are on the V8 heap, they get copied into `storage`. Otherwise
/// a view into the off-heap backing store is returned. The provided storage
/// should be at least as large as the maximum on-heap size of a TypedArray,
/// which is available as `v8::TYPED_ARRAY_MAX_SIZE_IN_HEAP`.
#[inline(always)]
pub fn get_contents<'s, 'a>(&'s self, storage: &'a mut [u8]) -> &'a [u8]
where
's: 'a,
{
unsafe {
let (data, size) = self.get_contents_raw_parts(storage);
if data.is_null() {
debug_assert_eq!(size, 0);
std::slice::from_raw_parts(std::ptr::dangling(), size)
} else {
std::slice::from_raw_parts(data, size)
}
}
}
}