Skip to content

Commit

Permalink
Merge pull request #1014 from alexcrichton/more-types
Browse files Browse the repository at this point in the history
Make `to_idl_type` infallible
  • Loading branch information
alexcrichton authored Nov 7, 2018
2 parents 5baa6ed + 3d1f426 commit d646b29
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 79 deletions.
28 changes: 27 additions & 1 deletion crates/web-sys/tests/wasm/response.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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);
}
})
}
122 changes: 60 additions & 62 deletions crates/webidl/src/idl_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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),
Expand All @@ -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),
Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -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),
Expand All @@ -288,51 +284,51 @@ 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:
//
// https://html.spec.whatwg.org/multipage/window-object.html#windowproxy
//
// 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)
}
}
}

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
}
}
)*)
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -587,6 +584,7 @@ impl<'a> IdlType<'a> {
}
IdlType::Void => None,
IdlType::Callback => js_sys("Function"),
IdlType::UnknownInterface(_) => None,
}
}

Expand Down
8 changes: 2 additions & 6 deletions crates/webidl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 => {
Expand Down
Loading

0 comments on commit d646b29

Please sign in to comment.