Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix as_slice and as_mut_slice for empty Buffers and ArrayBuffers #681

Merged
merged 1 commit into from
Feb 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/types/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,13 @@ impl<'a> BinaryData<'a> {
/// # }
/// ```
pub fn as_slice<T: BinaryViewType>(self) -> &'a [T] {
let base = unsafe { mem::transmute(self.base) };
let len = self.size / mem::size_of::<T>();
unsafe { slice::from_raw_parts(base, len) }
if self.size == 0 {
&[]
} else {
let base = unsafe { mem::transmute(self.base) };
let len = self.size / mem::size_of::<T>();
unsafe { slice::from_raw_parts(base, len) }
}
}

/// Produces a mutable slice as a view into the contents of this buffer.
Expand All @@ -160,9 +164,13 @@ impl<'a> BinaryData<'a> {
/// # }
/// ```
pub fn as_mut_slice<T: BinaryViewType>(self) -> &'a mut [T] {
let base = unsafe { mem::transmute(self.base) };
let len = self.size / mem::size_of::<T>();
unsafe { slice::from_raw_parts_mut(base, len) }
if self.size == 0 {
&mut []
} else {
let base = unsafe { mem::transmute(self.base) };
let len = self.size / mem::size_of::<T>();
unsafe { slice::from_raw_parts_mut(base, len) }
}
}

/// Produces the length of the buffer, in bytes.
Expand Down
36 changes: 36 additions & 0 deletions test/dynamic/lib/objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ describe('JsObject', function() {
assert.equal(addon.read_array_buffer_with_borrow(b, 3), 89898989);
});

it('correctly reads an empty ArrayBuffer using the borrow API', function() {
let nonempty = Uint8Array.from([1, 2, 3]);
assert.equal(addon.sum_array_buffer_with_borrow(nonempty.buffer), 6);

let empty = Uint8Array.from([]);
assert.equal(addon.sum_array_buffer_with_borrow(empty.buffer), 0);
});

it('correctly writes to an ArrayBuffer using the lock API', function() {
var b = new ArrayBuffer(16);
addon.write_array_buffer_with_lock(b, 0, 999);
Expand All @@ -81,6 +89,16 @@ describe('JsObject', function() {
assert.equal((new Uint32Array(b))[3], 400100);
});

it('correctly writes to an empty ArrayBuffer using the borrow API', function() {
let nonempty = Uint8Array.from([1, 2, 3]);
addon.increment_array_buffer_with_borrow_mut(nonempty.buffer);
assert.deepEqual(Array.from(nonempty), [2, 3, 4]);

let empty = Uint8Array.from([]);
addon.increment_array_buffer_with_borrow_mut(empty.buffer);
assert.deepEqual(Array.from(empty), []);
});

it('gets a 16-byte, zeroed Buffer', function() {
var b = addon.return_buffer();
assert.ok(b.equals(Buffer.alloc(16)));
Expand Down Expand Up @@ -110,6 +128,14 @@ describe('JsObject', function() {
assert.equal(addon.read_buffer_with_borrow(b, 3), 22914478);
});

it('correctly reads an empty Buffer using the borrow API', function() {
let nonempty = Buffer.from([1, 2, 3]);
assert.equal(addon.sum_buffer_with_borrow(nonempty), 6);

let empty = Buffer.from([]);
assert.equal(addon.sum_buffer_with_borrow(empty), 0);
});

it('correctly writes to a Buffer using the lock API', function() {
var b = Buffer.allocUnsafe(16);
b.fill(0);
Expand All @@ -135,4 +161,14 @@ describe('JsObject', function() {
addon.write_buffer_with_borrow_mut(b, 3, 66012);
assert.equal(b.readUInt32LE(12), 66012);
});

it('correctly writes to an empty Buffer using the borrow API', function() {
let nonempty = Buffer.from([1, 2, 3]);
addon.increment_buffer_with_borrow_mut(nonempty);
assert.deepEqual(Array.from(nonempty), [2, 3, 4]);

let empty = Buffer.from([]);
addon.increment_buffer_with_borrow_mut(empty);
assert.deepEqual(Array.from(empty), []);
});
});
24 changes: 24 additions & 0 deletions test/dynamic/native/src/js/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ pub fn read_array_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumb
Ok(cx.number(x))
}

pub fn sum_array_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {
let b: Handle<JsArrayBuffer> = cx.argument(0)?;
let x: u8 = cx.borrow(&b, |data| { data.as_slice::<u8>().iter().sum() });
Ok(cx.number(x))
}

pub fn write_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsArrayBuffer> = cx.argument(0)?;
let i = cx.argument::<JsNumber>(1)?.value() as u32 as usize;
Expand All @@ -76,6 +82,12 @@ pub fn write_array_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<J
Ok(cx.undefined())
}

pub fn increment_array_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsArrayBuffer> = cx.argument(0)?;
cx.borrow_mut(&mut b, |data| { data.as_mut_slice::<i8>().iter_mut().for_each(|x| *x += 1); });
Ok(cx.undefined())
}

pub fn return_buffer(mut cx: FunctionContext) -> JsResult<JsBuffer> {
let b: Handle<JsBuffer> = cx.buffer(16)?;
Ok(b)
Expand All @@ -100,6 +112,12 @@ pub fn read_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {
Ok(cx.number(x))
}

pub fn sum_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {
let b: Handle<JsBuffer> = cx.argument(0)?;
let x: u8 = cx.borrow(&b, |data| { data.as_slice::<u8>().iter().sum() });
Ok(cx.number(x))
}

pub fn write_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsBuffer> = cx.argument(0)?;
let i = cx.argument::<JsNumber>(1)?.value() as u32 as usize;
Expand All @@ -120,3 +138,9 @@ pub fn write_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndef
cx.borrow_mut(&mut b, |data| { data.as_mut_slice::<u32>()[i] = x; });
Ok(cx.undefined())
}

pub fn increment_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsBuffer> = cx.argument(0)?;
cx.borrow_mut(&mut b, |data| { data.as_mut_slice::<i8>().iter_mut().for_each(|x| *x += 1); });
Ok(cx.undefined())
}
4 changes: 4 additions & 0 deletions test/dynamic/native/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
cx.export_function("return_array_buffer", return_array_buffer)?;
cx.export_function("read_array_buffer_with_lock", read_array_buffer_with_lock)?;
cx.export_function("read_array_buffer_with_borrow", read_array_buffer_with_borrow)?;
cx.export_function("sum_array_buffer_with_borrow", sum_array_buffer_with_borrow)?;
cx.export_function("write_array_buffer_with_lock", write_array_buffer_with_lock)?;
cx.export_function("write_array_buffer_with_borrow_mut", write_array_buffer_with_borrow_mut)?;
cx.export_function("increment_array_buffer_with_borrow_mut", increment_array_buffer_with_borrow_mut)?;
cx.export_function("return_buffer", return_buffer)?;
cx.export_function("read_buffer_with_lock", read_buffer_with_lock)?;
cx.export_function("read_buffer_with_borrow", read_buffer_with_borrow)?;
cx.export_function("sum_buffer_with_borrow", sum_buffer_with_borrow)?;
cx.export_function("write_buffer_with_lock", write_buffer_with_lock)?;
cx.export_function("write_buffer_with_borrow_mut", write_buffer_with_borrow_mut)?;
cx.export_function("increment_buffer_with_borrow_mut", increment_buffer_with_borrow_mut)?;

cx.export_function("return_js_function", return_js_function)?;
cx.export_function("call_js_function", call_js_function)?;
Expand Down
24 changes: 24 additions & 0 deletions test/napi/src/js/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ pub fn read_array_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumb
Ok(cx.number(x))
}

pub fn sum_array_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {
let b: Handle<JsArrayBuffer> = cx.argument(0)?;
let x: u8 = cx.borrow(&b, |data| { data.as_slice::<u8>().iter().sum() });
Ok(cx.number(x))
}

pub fn write_array_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsArrayBuffer> = cx.argument(0)?;
let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as u32 as usize;
Expand All @@ -76,6 +82,12 @@ pub fn write_array_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<J
Ok(cx.undefined())
}

pub fn increment_array_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsArrayBuffer> = cx.argument(0)?;
cx.borrow_mut(&mut b, |data| { data.as_mut_slice::<i8>().iter_mut().for_each(|x| *x += 1); });
Ok(cx.undefined())
}

pub fn return_uninitialized_buffer(mut cx: FunctionContext) -> JsResult<JsBuffer> {
let b: Handle<JsBuffer> = unsafe { JsBuffer::uninitialized(&mut cx, 16)? };
Ok(b)
Expand Down Expand Up @@ -105,6 +117,12 @@ pub fn read_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {
Ok(cx.number(x))
}

pub fn sum_buffer_with_borrow(mut cx: FunctionContext) -> JsResult<JsNumber> {
let b: Handle<JsBuffer> = cx.argument(0)?;
let x: u8 = cx.borrow(&b, |data| { data.as_slice::<u8>().iter().sum() });
Ok(cx.number(x))
}

pub fn write_buffer_with_lock(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsBuffer> = cx.argument(0)?;
let i = cx.argument::<JsNumber>(1)?.value(&mut cx) as u32 as usize;
Expand All @@ -125,3 +143,9 @@ pub fn write_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndef
cx.borrow_mut(&mut b, |data| { data.as_mut_slice::<u32>()[i] = x; });
Ok(cx.undefined())
}

pub fn increment_buffer_with_borrow_mut(mut cx: FunctionContext) -> JsResult<JsUndefined> {
let mut b: Handle<JsBuffer> = cx.argument(0)?;
cx.borrow_mut(&mut b, |data| { data.as_mut_slice::<i8>().iter_mut().for_each(|x| *x += 1); });
Ok(cx.undefined())
}
4 changes: 4 additions & 0 deletions test/napi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,18 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
cx.export_function("return_array_buffer", return_array_buffer)?;
cx.export_function("read_array_buffer_with_lock", read_array_buffer_with_lock)?;
cx.export_function("read_array_buffer_with_borrow", read_array_buffer_with_borrow)?;
cx.export_function("sum_array_buffer_with_borrow", sum_array_buffer_with_borrow)?;
cx.export_function("write_array_buffer_with_lock", write_array_buffer_with_lock)?;
cx.export_function("write_array_buffer_with_borrow_mut", write_array_buffer_with_borrow_mut)?;
cx.export_function("increment_array_buffer_with_borrow_mut", increment_array_buffer_with_borrow_mut)?;
cx.export_function("return_uninitialized_buffer", return_uninitialized_buffer)?;
cx.export_function("return_buffer", return_buffer)?;
cx.export_function("read_buffer_with_lock", read_buffer_with_lock)?;
cx.export_function("read_buffer_with_borrow", read_buffer_with_borrow)?;
cx.export_function("sum_buffer_with_borrow", sum_buffer_with_borrow)?;
cx.export_function("write_buffer_with_lock", write_buffer_with_lock)?;
cx.export_function("write_buffer_with_borrow_mut", write_buffer_with_borrow_mut)?;
cx.export_function("increment_buffer_with_borrow_mut", increment_buffer_with_borrow_mut)?;

cx.export_function("create_date", create_date)?;
cx.export_function("get_date_value", get_date_value)?;
Expand Down