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::JsCast;
use wasm_bindgen_futures::JsFuture;
use wasm_bindgen_test::*;
use web_sys::Response;
@ -8,9 +16,27 @@ extern "C" {
}
#[wasm_bindgen_test]
fn test_response() {
fn test_response_from_js() {
let response = new_response();
assert!(!response.ok());
assert!(!response.redirected());
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,
Void,
UnknownInterface(&'a str),
}
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> {
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());
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> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self {
Type::Single(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> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self {
SingleType::Any(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> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self {
NonAnyType::Promise(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> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
Some(IdlType::Sequence(Box::new(
self.generics.body.to_idl_type(record)?,
)))
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
IdlType::Sequence(Box::new(self.generics.body.to_idl_type(record)))
}
}
impl<'a> ToIdlType<'a> for FrozenArrayType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
Some(IdlType::FrozenArray(Box::new(
self.generics.body.to_idl_type(record)?,
)))
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
IdlType::FrozenArray(Box::new(self.generics.body.to_idl_type(record)))
}
}
impl<'a, T: ToIdlType<'a>> ToIdlType<'a> for MayBeNull<T> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
let inner_idl_type = self.type_.to_idl_type(record)?;
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
let inner_idl_type = self.type_.to_idl_type(record);
if self.q_mark.is_some() {
Some(IdlType::Nullable(Box::new(inner_idl_type)))
IdlType::Nullable(Box::new(inner_idl_type))
} else {
Some(inner_idl_type)
inner_idl_type
}
}
}
impl<'a> ToIdlType<'a> for PromiseType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
Some(IdlType::Promise(Box::new(
self.generics.body.to_idl_type(record)?,
)))
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
IdlType::Promise(Box::new(self.generics.body.to_idl_type(record)))
}
}
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 {
IntegerType::LongLong(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 {
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() {
Some(IdlType::UnsignedLongLong)
IdlType::UnsignedLongLong
} else {
Some(IdlType::LongLong)
IdlType::LongLong
}
}
}
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() {
Some(IdlType::UnsignedLong)
IdlType::UnsignedLong
} else {
Some(IdlType::Long)
IdlType::Long
}
}
}
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() {
Some(IdlType::UnsignedShort)
IdlType::UnsignedShort
} else {
Some(IdlType::Short)
IdlType::Short
}
}
}
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 {
FloatingPointType::Float(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 {
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() {
Some(IdlType::UnrestrictedFloat)
IdlType::UnrestrictedFloat
} else {
Some(IdlType::Float)
IdlType::Float
}
}
}
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() {
Some(IdlType::UnrestrictedDouble)
IdlType::UnrestrictedDouble
} else {
Some(IdlType::Double)
IdlType::Double
}
}
}
impl<'a> ToIdlType<'a> for RecordType<'a> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
Some(IdlType::Record(
Box::new(self.generics.body.0.to_idl_type(record)?),
Box::new(self.generics.body.2.to_idl_type(record)?),
))
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
IdlType::Record(
Box::new(self.generics.body.0.to_idl_type(record)),
Box::new(self.generics.body.2.to_idl_type(record)),
)
}
}
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 {
StringType::Byte(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> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self {
UnionMemberType::Single(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> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self {
ConstType::Integer(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> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
fn to_idl_type(&self, record: &FirstPassRecord<'a>) -> IdlType<'a> {
match self {
ReturnType::Void(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> {
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)
}
}
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" {
// https://heycam.github.io/webidl/#DOMTimeStamp
Some(IdlType::UnsignedLongLong)
IdlType::UnsignedLongLong
} else if let Some(idl_type) = record.typedefs.get(&self.0) {
idl_type.to_idl_type(record)
} 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) {
Some(IdlType::Dictionary(self.0))
IdlType::Dictionary(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) {
Some(IdlType::Callback)
IdlType::Callback
} else if let Some(data) = record.callback_interfaces.get(self.0) {
Some(IdlType::CallbackInterface {
IdlType::CallbackInterface {
name: self.0,
single_function: data.single_function,
})
}
} else if self.0 == "WindowProxy" {
// 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
// let's translate it as such.
Some(IdlType::Interface("Window"))
IdlType::Interface("Window")
} else {
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 {
($($t:tt => $r:tt)*) => ($(
impl<'a> ToIdlType<'a> for term::$t {
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> Option<IdlType<'a>> {
Some(IdlType::$r)
fn to_idl_type(&self, _record: &FirstPassRecord<'a>) -> IdlType<'a> {
IdlType::$r
}
}
)*)
@ -406,6 +402,7 @@ impl<'a> IdlType<'a> {
IdlType::BufferSource => dst.push_str("buffer_source"),
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::Enum(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::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
let ty = field
.type_
.to_idl_type(self)?
.to_idl_type(self)
.to_syn_type(TypePosition::Argument)?;
// Slice types aren't supported because they don't implement
@ -459,11 +459,7 @@ impl<'src> FirstPassRecord<'src> {
self_name: &'src str,
member: &'src weedle::interface::ConstMember<'src>,
) {
let idl_type = match member.const_type.to_idl_type(self) {
Some(idl_type) => idl_type,
None => return,
};
let idl_type = member.const_type.to_idl_type(self);
let ty = match idl_type.to_syn_type(TypePosition::Return) {
Some(ty) => ty,
None => {

View File

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