conversions: Add a checked version to array_buffer_view_data

This commit is contained in:
Emilio Cobos Álvarez 2016-01-04 15:18:40 +01:00
parent 9ad49c8aa1
commit 43d395a682
3 changed files with 35 additions and 12 deletions

View file

@ -46,9 +46,10 @@ use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_STRING, UnwrapObject};
use js::jsapi::{HandleId, HandleObject, HandleValue, JS_GetClass}; use js::jsapi::{HandleId, HandleObject, HandleValue, JS_GetClass};
use js::jsapi::{JSClass, JSContext, JSObject, MutableHandleValue}; use js::jsapi::{JSClass, JSContext, JSObject, MutableHandleValue};
use js::jsapi::{JS_GetLatin1StringCharsAndLength, JS_GetReservedSlot}; use js::jsapi::{JS_GetLatin1StringCharsAndLength, JS_GetReservedSlot};
use js::jsapi::{JS_GetObjectAsArrayBufferView, JS_GetArrayBufferViewType};
use js::jsapi::{JS_GetTwoByteStringCharsAndLength, JS_NewStringCopyN}; use js::jsapi::{JS_GetTwoByteStringCharsAndLength, JS_NewStringCopyN};
use js::jsapi::{JS_StringHasLatin1Chars, JS_WrapValue}; use js::jsapi::{JS_StringHasLatin1Chars, JS_WrapValue};
use js::jsapi::{JS_GetObjectAsArrayBufferView}; use js::jsapi::{Type};
use js::jsval::{ObjectValue, StringValue}; use js::jsval::{ObjectValue, StringValue};
use js::rust::ToString; use js::rust::ToString;
use libc; use libc;
@ -348,7 +349,8 @@ unsafe impl ArrayBufferViewContents for i32 {}
unsafe impl ArrayBufferViewContents for f32 {} unsafe impl ArrayBufferViewContents for f32 {}
unsafe impl ArrayBufferViewContents for f64 {} unsafe impl ArrayBufferViewContents for f64 {}
/// Returns a mutable slice of the Array Buffer View data, viewed as T /// Returns a mutable slice of the Array Buffer View data, viewed as T, without checking the real
/// type of it.
pub unsafe fn array_buffer_view_data<'a, T: ArrayBufferViewContents>(abv: *mut JSObject) -> Option<&'a mut [T]> { pub unsafe fn array_buffer_view_data<'a, T: ArrayBufferViewContents>(abv: *mut JSObject) -> Option<&'a mut [T]> {
let mut byte_length = 0; let mut byte_length = 0;
let mut ptr = ptr::null_mut(); let mut ptr = ptr::null_mut();
@ -359,9 +361,31 @@ pub unsafe fn array_buffer_view_data<'a, T: ArrayBufferViewContents>(abv: *mut J
Some(slice::from_raw_parts_mut(ptr as *mut T, byte_length as usize / mem::size_of::<T>())) Some(slice::from_raw_parts_mut(ptr as *mut T, byte_length as usize / mem::size_of::<T>()))
} }
/// Returns a copy of the ArrayBufferView data /// Returns a copy of the ArrayBufferView data, viewed as T, without checking the real type of it.
pub fn array_buffer_view_to_vec<T: ArrayBufferViewContents>(abv: *mut JSObject) -> Option<Vec<T>> { pub fn array_buffer_view_to_vec<T: ArrayBufferViewContents>(abv: *mut JSObject) -> Option<Vec<T>> {
unsafe { unsafe {
array_buffer_view_data(abv).map(|data| data.to_vec()) array_buffer_view_data(abv).map(|data| data.to_vec())
} }
} }
/// Returns a mutable slice of the Array Buffer View data, viewed as T, checking that the real type
/// of it is ty.
pub unsafe fn array_buffer_view_data_checked<'a, T: ArrayBufferViewContents>(abv: *mut JSObject,
ty: Type) -> Option<&'a mut [T]> {
array_buffer_view_data::<T>(abv).and_then(|data| {
let real_ty = JS_GetArrayBufferViewType(abv);
if real_ty as i32 == ty as i32 {
Some(data)
} else {
None
}
})
}
/// Returns a copy of the ArrayBufferView data, viewed as T, checking that the real type
/// of it is ty.
pub fn array_buffer_view_to_vec_checked<T: ArrayBufferViewContents>(abv: *mut JSObject, ty: Type) -> Option<Vec<T>> {
unsafe {
array_buffer_view_data_checked(abv, ty).map(|data| data.to_vec())
}
}

View file

@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::conversions::array_buffer_view_data;
use dom::bindings::codegen::Bindings::CryptoBinding; use dom::bindings::codegen::Bindings::CryptoBinding;
use dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods; use dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods;
use dom::bindings::conversions::array_buffer_view_data;
use dom::bindings::error::{Error, Fallible}; use dom::bindings::error::{Error, Fallible};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root; use dom::bindings::js::Root;

View file

@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderi
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{WebGLRenderingContextMethods}; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{WebGLRenderingContextMethods};
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes}; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes};
use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement; use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
use dom::bindings::conversions::{ToJSValConvertible, array_buffer_view_to_vec}; use dom::bindings::conversions::{ToJSValConvertible, array_buffer_view_to_vec_checked, array_buffer_view_to_vec};
use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::inheritance::Castable; use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root};
@ -28,7 +28,7 @@ use dom::webgltexture::{TexParameterValue, WebGLTexture};
use dom::webgluniformlocation::WebGLUniformLocation; use dom::webgluniformlocation::WebGLUniformLocation;
use euclid::size::Size2D; use euclid::size::Size2D;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::{JSContext, JSObject, RootedValue}; use js::jsapi::{JSContext, JSObject, RootedValue, Type};
use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UndefinedValue};
use net_traits::image::base::PixelFormat; use net_traits::image::base::PixelFormat;
use net_traits::image_cache_task::ImageResponse; use net_traits::image_cache_task::ImageResponse;
@ -948,7 +948,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
None => return, None => return,
}; };
if let Some(data_vec) = array_buffer_view_to_vec::<f32>(data) { if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data, Type::Float32) {
if data_vec.len() < 4 { if data_vec.len() < 4 {
return self.webgl_error(InvalidOperation); return self.webgl_error(InvalidOperation);
} }
@ -976,7 +976,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
fn VertexAttrib1fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib1fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
if let Some(data_vec) = array_buffer_view_to_vec::<f32>(data) { if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data, Type::Float32) {
if data_vec.len() < 4 { if data_vec.len() < 4 {
return self.webgl_error(InvalidOperation); return self.webgl_error(InvalidOperation);
} }
@ -994,7 +994,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
fn VertexAttrib2fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib2fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
if let Some(data_vec) = array_buffer_view_to_vec::<f32>(data) { if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data, Type::Float32) {
if data_vec.len() < 2 { if data_vec.len() < 2 {
return self.webgl_error(InvalidOperation); return self.webgl_error(InvalidOperation);
} }
@ -1012,7 +1012,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
fn VertexAttrib3fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib3fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
if let Some(data_vec) = array_buffer_view_to_vec::<f32>(data) { if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data, Type::Float32) {
if data_vec.len() < 3 { if data_vec.len() < 3 {
return self.webgl_error(InvalidOperation); return self.webgl_error(InvalidOperation);
} }
@ -1027,10 +1027,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
self.vertex_attrib(indx, x, y, z, w) self.vertex_attrib(indx, x, y, z, w)
} }
#[allow(unsafe_code)]
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
fn VertexAttrib4fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) { fn VertexAttrib4fv(&self, _cx: *mut JSContext, indx: u32, data: *mut JSObject) {
if let Some(data_vec) = array_buffer_view_to_vec::<f32>(data) { if let Some(data_vec) = array_buffer_view_to_vec_checked::<f32>(data, Type::Float32) {
if data_vec.len() < 4 { if data_vec.len() < 4 {
return self.webgl_error(InvalidOperation); return self.webgl_error(InvalidOperation);
} }