Merge pull request #1014 from alexcrichton/more-types

Make `to_idl_type` infallible
This commit is contained in:
Alex Crichton 2018-11-07 15:32:45 -06:00 committed by GitHub
commit d646b29bb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 79 deletions

View File

@ -1,4 +1,12 @@
extern crate futures;
extern crate js_sys;
extern crate wasm_bindgen_futures;
use futures::Future;
use js_sys::{ArrayBuffer, DataView};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use wasm_bindgen_test::*; use wasm_bindgen_test::*;
use web_sys::Response; use web_sys::Response;
@ -8,9 +16,27 @@ extern "C" {
} }
#[wasm_bindgen_test] #[wasm_bindgen_test]
fn test_response() { fn test_response_from_js() {
let response = new_response(); let response = new_response();
assert!(!response.ok()); assert!(!response.ok());
assert!(!response.redirected()); assert!(!response.redirected());
assert_eq!(response.status(), 501); assert_eq!(response.status(), 501);
} }
#[wasm_bindgen_test(async)]
fn test_response_from_bytes() -> impl Future<Item = (), Error = JsValue> {
let mut bytes: [u8; 3] = [1, 3, 5];
let response = Response::new_with_opt_u8_array(Some(&mut bytes)).unwrap();
assert!(response.ok());
assert_eq!(response.status(), 200);
let buf_promise = response.array_buffer().unwrap();
JsFuture::from(buf_promise).map(move |buf_val| {
assert!(buf_val.is_instance_of::<ArrayBuffer>());
let array_buf: ArrayBuffer = buf_val.dyn_into().unwrap();
let data_view = DataView::new(&array_buf, 0, bytes.len());
for (i, byte) in bytes.iter().enumerate() {
assert_eq!(&data_view.get_uint8(i), byte);
}
})
}

View File

@ -63,24 +63,26 @@ pub(crate) enum IdlType<'a> {
Any, Any,
Void, Void,
UnknownInterface(&'a str),
} }
pub(crate) trait ToIdlType<'a> { pub(crate) trait ToIdlType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>>; fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a>;
} }
impl<'a> ToIdlType<'a> for UnionType<'a> { impl<'a> ToIdlType<'a> for UnionType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
let mut idl_types = Vec::with_capacity(self.body.list.len()); let mut idl_types = Vec::with_capacity(self.body.list.len());
for t in &self.body.list { for t in &self.body.list {
idl_types.push(t.to_idl_type(record)?); idl_types.push(t.to_idl_type(record));
} }
Some(IdlType::Union(idl_types)) IdlType::Union(idl_types)
} }
} }
impl<'a> ToIdlType<'a> for Type<'a> { impl<'a> ToIdlType<'a> for Type<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
Type::Single(t) => t.to_idl_type(record), Type::Single(t) => t.to_idl_type(record),
Type::Union(t) => t.to_idl_type(record), Type::Union(t) => t.to_idl_type(record),
@ -89,7 +91,7 @@ impl<'a> ToIdlType<'a> for Type<'a> {
} }
impl<'a> ToIdlType<'a> for SingleType<'a> { impl<'a> ToIdlType<'a> for SingleType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
SingleType::Any(t) => t.to_idl_type(record), SingleType::Any(t) => t.to_idl_type(record),
SingleType::NonAny(t) => t.to_idl_type(record), SingleType::NonAny(t) => t.to_idl_type(record),
@ -98,7 +100,7 @@ impl<'a> ToIdlType<'a> for SingleType<'a> {
} }
impl<'a> ToIdlType<'a> for NonAnyType<'a> { impl<'a> ToIdlType<'a> for NonAnyType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
NonAnyType::Promise(t) => t.to_idl_type(record), NonAnyType::Promise(t) => t.to_idl_type(record),
NonAnyType::Integer(t) => t.to_idl_type(record), NonAnyType::Integer(t) => t.to_idl_type(record),
@ -134,42 +136,36 @@ impl<'a> ToIdlType<'a> for NonAnyType<'a> {
} }
impl<'a> ToIdlType<'a> for SequenceType<'a> { impl<'a> ToIdlType<'a> for SequenceType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
Some(IdlType::Sequence(Box::new( IdlType::Sequence(Box::new(self.generics.body.to_idl_type(record)))
self.generics.body.to_idl_type(record)?,
)))
} }
} }
impl<'a> ToIdlType<'a> for FrozenArrayType<'a> { impl<'a> ToIdlType<'a> for FrozenArrayType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
Some(IdlType::FrozenArray(Box::new( IdlType::FrozenArray(Box::new(self.generics.body.to_idl_type(record)))
self.generics.body.to_idl_type(record)?,
)))
} }
} }
impl<'a, T: ToIdlType<'a>> ToIdlType<'a> for MayBeNull<T> { impl<'a, T: ToIdlType<'a>> ToIdlType<'a> for MayBeNull<T> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
let inner_idl_type = self.type_.to_idl_type(record)?; let inner_idl_type = self.type_.to_idl_type(record);
if self.q_mark.is_some() { if self.q_mark.is_some() {
Some(IdlType::Nullable(Box::new(inner_idl_type))) IdlType::Nullable(Box::new(inner_idl_type))
} else { } else {
Some(inner_idl_type) inner_idl_type
} }
} }
} }
impl<'a> ToIdlType<'a> for PromiseType<'a> { impl<'a> ToIdlType<'a> for PromiseType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
Some(IdlType::Promise(Box::new( IdlType::Promise(Box::new(self.generics.body.to_idl_type(record)))
self.generics.body.to_idl_type(record)?,
)))
} }
} }
impl<'a> ToIdlType<'a> for IntegerType { impl<'a> ToIdlType<'a> for IntegerType {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
IntegerType::LongLong(t) => t.to_idl_type(record), IntegerType::LongLong(t) => t.to_idl_type(record),
IntegerType::Long(t) => t.to_idl_type(record), IntegerType::Long(t) => t.to_idl_type(record),
@ -179,37 +175,37 @@ impl<'a> ToIdlType<'a> for IntegerType {
} }
impl<'a> ToIdlType<'a> for LongLongType { impl<'a> ToIdlType<'a> for LongLongType {
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
if self.unsigned.is_some() { if self.unsigned.is_some() {
Some(IdlType::UnsignedLongLong) IdlType::UnsignedLongLong
} else { } else {
Some(IdlType::LongLong) IdlType::LongLong
} }
} }
} }
impl<'a> ToIdlType<'a> for LongType { impl<'a> ToIdlType<'a> for LongType {
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
if self.unsigned.is_some() { if self.unsigned.is_some() {
Some(IdlType::UnsignedLong) IdlType::UnsignedLong
} else { } else {
Some(IdlType::Long) IdlType::Long
} }
} }
} }
impl<'a> ToIdlType<'a> for ShortType { impl<'a> ToIdlType<'a> for ShortType {
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
if self.unsigned.is_some() { if self.unsigned.is_some() {
Some(IdlType::UnsignedShort) IdlType::UnsignedShort
} else { } else {
Some(IdlType::Short) IdlType::Short
} }
} }
} }
impl<'a> ToIdlType<'a> for FloatingPointType { impl<'a> ToIdlType<'a> for FloatingPointType {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
FloatingPointType::Float(t) => t.to_idl_type(record), FloatingPointType::Float(t) => t.to_idl_type(record),
FloatingPointType::Double(t) => t.to_idl_type(record), FloatingPointType::Double(t) => t.to_idl_type(record),
@ -218,36 +214,36 @@ impl<'a> ToIdlType<'a> for FloatingPointType {
} }
impl<'a> ToIdlType<'a> for FloatType { impl<'a> ToIdlType<'a> for FloatType {
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
if self.unrestricted.is_some() { if self.unrestricted.is_some() {
Some(IdlType::UnrestrictedFloat) IdlType::UnrestrictedFloat
} else { } else {
Some(IdlType::Float) IdlType::Float
} }
} }
} }
impl<'a> ToIdlType<'a> for DoubleType { impl<'a> ToIdlType<'a> for DoubleType {
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
if self.unrestricted.is_some() { if self.unrestricted.is_some() {
Some(IdlType::UnrestrictedDouble) IdlType::UnrestrictedDouble
} else { } else {
Some(IdlType::Double) IdlType::Double
} }
} }
} }
impl<'a> ToIdlType<'a> for RecordType<'a> { impl<'a> ToIdlType<'a> for RecordType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
Some(IdlType::Record( IdlType::Record(
Box::new(self.generics.body.0.to_idl_type(record)?), Box::new(self.generics.body.0.to_idl_type(record)),
Box::new(self.generics.body.2.to_idl_type(record)?), Box::new(self.generics.body.2.to_idl_type(record)),
)) )
} }
} }
impl<'a> ToIdlType<'a> for StringType { impl<'a> ToIdlType<'a> for StringType {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
StringType::Byte(t) => t.to_idl_type(record), StringType::Byte(t) => t.to_idl_type(record),
StringType::DOM(t) => t.to_idl_type(record), StringType::DOM(t) => t.to_idl_type(record),
@ -257,7 +253,7 @@ impl<'a> ToIdlType<'a> for StringType {
} }
impl<'a> ToIdlType<'a> for UnionMemberType<'a> { impl<'a> ToIdlType<'a> for UnionMemberType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
UnionMemberType::Single(t) => t.to_idl_type(record), UnionMemberType::Single(t) => t.to_idl_type(record),
UnionMemberType::Union(t) => t.to_idl_type(record), UnionMemberType::Union(t) => t.to_idl_type(record),
@ -266,7 +262,7 @@ impl<'a> ToIdlType<'a> for UnionMemberType<'a> {
} }
impl<'a> ToIdlType<'a> for ConstType<'a> { impl<'a> ToIdlType<'a> for ConstType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
ConstType::Integer(t) => t.to_idl_type(record), ConstType::Integer(t) => t.to_idl_type(record),
ConstType::FloatingPoint(t) => t.to_idl_type(record), ConstType::FloatingPoint(t) => t.to_idl_type(record),
@ -279,7 +275,7 @@ impl<'a> ToIdlType<'a> for ConstType<'a> {
} }
impl<'a> ToIdlType<'a> for ReturnType<'a> { impl<'a> ToIdlType<'a> for ReturnType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self { match self {
ReturnType::Void(t) => t.to_idl_type(record), ReturnType::Void(t) => t.to_idl_type(record),
ReturnType::Type(t) => t.to_idl_type(record), ReturnType::Type(t) => t.to_idl_type(record),
@ -288,31 +284,31 @@ impl<'a> ToIdlType<'a> for ReturnType<'a> {
} }
impl<'a> ToIdlType<'a> for AttributedType<'a> { impl<'a> ToIdlType<'a> for AttributedType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
self.type_.to_idl_type(record) self.type_.to_idl_type(record)
} }
} }
impl<'a> ToIdlType<'a> for Identifier<'a> { impl<'a> ToIdlType<'a> for Identifier<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
if self.0 == "DOMTimeStamp" { if self.0 == "DOMTimeStamp" {
// https://heycam.github.io/webidl/#DOMTimeStamp // https://heycam.github.io/webidl/#DOMTimeStamp
Some(IdlType::UnsignedLongLong) IdlType::UnsignedLongLong
} else if let Some(idl_type) = record.typedefs.get(&self.0) { } else if let Some(idl_type) = record.typedefs.get(&self.0) {
idl_type.to_idl_type(record) idl_type.to_idl_type(record)
} else if record.interfaces.contains_key(self.0) { } else if record.interfaces.contains_key(self.0) {
Some(IdlType::Interface(self.0)) IdlType::Interface(self.0)
} else if record.dictionaries.contains_key(self.0) { } else if record.dictionaries.contains_key(self.0) {
Some(IdlType::Dictionary(self.0)) IdlType::Dictionary(self.0)
} else if record.enums.contains_key(self.0) { } else if record.enums.contains_key(self.0) {
Some(IdlType::Enum(self.0)) IdlType::Enum(self.0)
} else if record.callbacks.contains(self.0) { } else if record.callbacks.contains(self.0) {
Some(IdlType::Callback) IdlType::Callback
} else if let Some(data) = record.callback_interfaces.get(self.0) { } else if let Some(data) = record.callback_interfaces.get(self.0) {
Some(IdlType::CallbackInterface { IdlType::CallbackInterface {
name: self.0, name: self.0,
single_function: data.single_function, single_function: data.single_function,
}) }
} else if self.0 == "WindowProxy" { } else if self.0 == "WindowProxy" {
// See this for more info: // See this for more info:
// //
@ -320,10 +316,10 @@ impl<'a> ToIdlType<'a> for Identifier<'a> {
// //
// namely this seems to be "legalese" for "this is a `Window`", so // namely this seems to be "legalese" for "this is a `Window`", so
// let's translate it as such. // let's translate it as such.
Some(IdlType::Interface("Window")) IdlType::Interface("Window")
} else { } else {
warn!("Unrecognized type: {}", self.0); warn!("Unrecognized type: {}", self.0);
None IdlType::UnknownInterface(self.0)
} }
} }
} }
@ -331,8 +327,8 @@ impl<'a> ToIdlType<'a> for Identifier<'a> {
macro_rules! terms_to_idl_type { macro_rules! terms_to_idl_type {
($($t:tt => $r:tt)*) => ($( ($($t:tt => $r:tt)*) => ($(
impl<'a> ToIdlType<'a> for term::$t { impl<'a> ToIdlType<'a> for term::$t {
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> { fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
Some(IdlType::$r) IdlType::$r
} }
} }
)*) )*)
@ -406,6 +402,7 @@ impl<'a> IdlType<'a> {
IdlType::BufferSource => dst.push_str("buffer_source"), IdlType::BufferSource => dst.push_str("buffer_source"),
IdlType::Interface(name) => dst.push_str(&snake_case_ident(name)), IdlType::Interface(name) => dst.push_str(&snake_case_ident(name)),
IdlType::UnknownInterface(name) => dst.push_str(&snake_case_ident(name)),
IdlType::Dictionary(name) => dst.push_str(&snake_case_ident(name)), IdlType::Dictionary(name) => dst.push_str(&snake_case_ident(name)),
IdlType::Enum(name) => dst.push_str(&snake_case_ident(name)), IdlType::Enum(name) => dst.push_str(&snake_case_ident(name)),
IdlType::CallbackInterface { name, .. } => dst.push_str(&snake_case_ident(name)), IdlType::CallbackInterface { name, .. } => dst.push_str(&snake_case_ident(name)),
@ -587,6 +584,7 @@ impl<'a> IdlType<'a> {
} }
IdlType::Void => None, IdlType::Void => None,
IdlType::Callback => js_sys("Function"), IdlType::Callback => js_sys("Function"),
IdlType::UnknownInterface(_) => None,
} }
} }

View File

@ -353,7 +353,7 @@ impl<'src> FirstPassRecord<'src> {
// use argument position now as we're just binding setters // use argument position now as we're just binding setters
let ty = field let ty = field
.type_ .type_
.to_idl_type(self)? .to_idl_type(self)
.to_syn_type(TypePosition::Argument)?; .to_syn_type(TypePosition::Argument)?;
// Slice types aren't supported because they don't implement // Slice types aren't supported because they don't implement
@ -459,11 +459,7 @@ impl<'src> FirstPassRecord<'src> {
self_name: &'src str, self_name: &'src str,
member: &'src weedle::interface::ConstMember<'src>, member: &'src weedle::interface::ConstMember<'src>,
) { ) {
let idl_type = match member.const_type.to_idl_type(self) { let idl_type = member.const_type.to_idl_type(self);
Some(idl_type) => idl_type,
None => return,
};
let ty = match idl_type.to_syn_type(TypePosition::Return) { let ty = match idl_type.to_syn_type(TypePosition::Return) {
Some(ty) => ty, Some(ty) => ty,
None => { None => {

View File

@ -336,7 +336,7 @@ impl<'src> FirstPassRecord<'src> {
) -> Option<backend::ast::ImportFunction> { ) -> Option<backend::ast::ImportFunction> {
let kind = backend::ast::OperationKind::Getter(Some(raw_ident(name))); let kind = backend::ast::OperationKind::Getter(Some(raw_ident(name)));
let kind = self.import_function_kind(self_name, is_static, kind); let kind = self.import_function_kind(self_name, is_static, kind);
let ret = ty.to_idl_type(self)?; let ret = ty.to_idl_type(self);
self.create_one_function( self.create_one_function(
&name, &name,
&snake_case_ident(name), &snake_case_ident(name),
@ -366,7 +366,7 @@ impl<'src> FirstPassRecord<'src> {
) -> Option<backend::ast::ImportFunction> { ) -> Option<backend::ast::ImportFunction> {
let kind = backend::ast::OperationKind::Setter(Some(raw_ident(name))); let kind = backend::ast::OperationKind::Setter(Some(raw_ident(name)));
let kind = self.import_function_kind(self_name, is_static, kind); let kind = self.import_function_kind(self_name, is_static, kind);
let field_ty = field_ty.to_idl_type(self)?; let field_ty = field_ty.to_idl_type(self);
self.create_one_function( self.create_one_function(
&name, &name,
&format!("set_{}", name).to_snake_case(), &format!("set_{}", name).to_snake_case(),
@ -431,10 +431,7 @@ impl<'src> FirstPassRecord<'src> {
); );
signatures.push((signature, idl_args.clone())); signatures.push((signature, idl_args.clone()));
} }
match arg.ty.to_idl_type(self) { idl_args.push(arg.ty.to_idl_type(self));
Some(t) => idl_args.push(t),
None => continue 'outer,
}
} }
signatures.push((signature, idl_args)); signatures.push((signature, idl_args));
} }
@ -517,10 +514,7 @@ impl<'src> FirstPassRecord<'src> {
// TODO: overloads probably never change return types, so we should // TODO: overloads probably never change return types, so we should
// do this much earlier to avoid all the above work if // do this much earlier to avoid all the above work if
// possible. // possible.
let ret_ty = match signature.orig.ret.to_idl_type(self) { let ret_ty = signature.orig.ret.to_idl_type(self);
Some(ty) => ty,
None => continue,
};
let mut rust_name = snake_case_ident(name); let mut rust_name = snake_case_ident(name);
let mut first = true; let mut first = true;