v8/
array_buffer_view.rs

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