use alloc::boxed::Box;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::future::Future;
use core::ops::AsyncFnOnce;
use super::{DecodeError, DecodedData, EncodedData, JsRef};
pub trait BinaryEncode {
fn encode(self, encoder: &mut EncodedData);
}
pub trait BinaryDecode: Sized {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError>;
}
pub trait JsRefEncode {
fn js_ref(&self) -> JsRef;
}
mod sealed {
pub trait Sealed {}
}
#[doc(hidden)]
pub trait BorrowScope: sealed::Sealed {}
#[doc(hidden)]
pub struct CallScoped;
#[doc(hidden)]
pub struct Anchored;
impl sealed::Sealed for CallScoped {}
impl sealed::Sealed for Anchored {}
impl BorrowScope for CallScoped {}
impl BorrowScope for Anchored {}
#[doc(hidden)]
pub trait ArgAbi<S: BorrowScope> {
type Wire: EncodeTypeDef;
type Guard;
type ProjectedGuard;
type Projected<'a>;
fn decode(decoder: &mut DecodedData) -> Result<Self::Guard, DecodeError>;
fn project<R, F>(guard: Self::Guard, with: F) -> (R, Self::ProjectedGuard)
where
F: for<'a> FnOnce(Self::Projected<'a>) -> R;
fn write_back(_guard: Self::ProjectedGuard, _encoder: &mut EncodedData) {}
fn project_async<R, F>(guard: Self::Guard, with: F) -> impl Future<Output = R>
where
F: for<'a> AsyncFnOnce(Self::Projected<'a>) -> R;
}
impl<S, T> ArgAbi<S> for T
where
S: BorrowScope,
T: BinaryDecode + EncodeTypeDef,
{
type Wire = T;
type Guard = T;
type ProjectedGuard = ();
type Projected<'a> = T;
fn decode(decoder: &mut DecodedData) -> Result<Self::Guard, DecodeError> {
<T as BinaryDecode>::decode(decoder)
}
fn project<R, F>(guard: Self::Guard, with: F) -> (R, Self::ProjectedGuard)
where
F: for<'a> FnOnce(Self::Projected<'a>) -> R,
{
let result = with(guard);
(result, ())
}
async fn project_async<R, F>(guard: Self::Guard, with: F) -> R
where
F: for<'a> AsyncFnOnce(Self::Projected<'a>) -> R,
{
with(guard).await
}
}
impl<S: BorrowScope> ArgAbi<S> for &str {
type Wire = String;
type Guard = String;
type ProjectedGuard = ();
type Projected<'a> = &'a str;
fn decode(decoder: &mut DecodedData) -> Result<Self::Guard, DecodeError> {
<String as BinaryDecode>::decode(decoder)
}
fn project<R, F>(guard: Self::Guard, with: F) -> (R, Self::ProjectedGuard)
where
F: for<'a> FnOnce(Self::Projected<'a>) -> R,
{
let result = with(&guard);
(result, ())
}
async fn project_async<R, F>(guard: Self::Guard, with: F) -> R
where
F: for<'a> AsyncFnOnce(Self::Projected<'a>) -> R,
{
with(&guard).await
}
}
impl<S, T> ArgAbi<S> for &[T]
where
S: BorrowScope,
T: BinaryDecode + EncodeTypeDef + 'static,
{
type Wire = Vec<T>;
type Guard = Vec<T>;
type ProjectedGuard = ();
type Projected<'a> = &'a [T];
fn decode(decoder: &mut DecodedData) -> Result<Self::Guard, DecodeError> {
<Vec<T> as BinaryDecode>::decode(decoder)
}
fn project<R, F>(guard: Self::Guard, with: F) -> (R, Self::ProjectedGuard)
where
F: for<'a> FnOnce(Self::Projected<'a>) -> R,
{
let result = with(&guard);
(result, ())
}
async fn project_async<R, F>(guard: Self::Guard, with: F) -> R
where
F: for<'a> AsyncFnOnce(Self::Projected<'a>) -> R,
{
with(&guard).await
}
}
impl<S, T> ArgAbi<S> for &mut [T]
where
S: BorrowScope,
T: BinaryDecode + BinaryEncode + EncodeTypeDef + 'static,
{
type Wire = MutSliceArg<T>;
type Guard = MutSliceArg<T>;
type ProjectedGuard = Self::Guard;
type Projected<'a> = &'a mut [T];
fn decode(decoder: &mut DecodedData) -> Result<Self::Guard, DecodeError> {
<MutSliceArg<T> as BinaryDecode>::decode(decoder)
}
fn project<R, F>(mut guard: Self::Guard, with: F) -> (R, Self::ProjectedGuard)
where
F: for<'a> FnOnce(Self::Projected<'a>) -> R,
{
let result = with(guard.as_mut_slice());
(result, guard)
}
fn write_back(guard: Self::ProjectedGuard, encoder: &mut EncodedData) {
MutSliceArg::write_back(guard, encoder);
}
async fn project_async<R, F>(mut guard: Self::Guard, with: F) -> R
where
F: for<'a> AsyncFnOnce(Self::Projected<'a>) -> R,
{
with(guard.as_mut_slice()).await
}
}
pub(crate) const TYPE_CACHED: u8 = 0xFF;
pub(crate) const TYPE_FULL: u8 = 0xFE;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum TypeTag {
Undefined = 0,
Bool = 1,
U8 = 2,
U16 = 3,
U32 = 4,
U64 = 5,
U128 = 6,
I8 = 7,
I16 = 8,
I32 = 9,
I64 = 10,
I128 = 11,
F32 = 12,
F64 = 13,
Usize = 14,
Isize = 15,
String = 16,
HeapRef = 17,
Callback = 18,
Option = 19,
Result = 20,
Array = 21,
BorrowedRef = 22,
U8Clamped = 23,
StringEnum = 24,
DynamicUnion = 25,
Char = 26,
ThrowingResult = 27,
NumericEnum = 28,
RustValue = 29,
RustBorrow = 30,
MutArray = 31,
}
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct TypeDef {
bytes: Vec<u8>,
}
#[derive(Clone, Copy)]
pub struct FunctionTypeInfo<'a> {
type_id: u32,
can_use_cached: bool,
type_def: &'a TypeDef,
}
impl<'a> FunctionTypeInfo<'a> {
pub const fn new(type_id: u32, can_use_cached: bool, type_def: &'a TypeDef) -> Self {
Self {
type_id,
can_use_cached,
type_def,
}
}
}
impl BinaryEncode for FunctionTypeInfo<'_> {
fn encode(self, encoder: &mut EncodedData) {
if self.can_use_cached {
encoder.push_u8(TYPE_CACHED);
encoder.push_u32(self.type_id);
} else {
encoder.push_u8(TYPE_FULL);
encoder.push_u32(self.type_id);
for &byte in self.type_def.bytes() {
encoder.push_u8(byte);
}
}
}
}
impl TypeDef {
pub fn of<T: EncodeTypeDef + ?Sized>() -> Self {
let mut type_def = TypeDef::default();
T::encode_type_def(&mut type_def);
type_def
}
pub(crate) fn bytes(&self) -> &[u8] {
&self.bytes
}
pub(crate) fn heap_ref(&mut self) {
self.push_tag(TypeTag::HeapRef);
}
#[doc(hidden)]
pub fn rust_value(&mut self, class_name: &str) {
self.push_tag(TypeTag::RustValue);
self.push_str(class_name);
}
#[doc(hidden)]
pub fn borrowed_ref(&mut self) {
self.push_tag(TypeTag::BorrowedRef);
}
#[doc(hidden)]
pub fn rust_borrow(&mut self, class_name: &str) {
self.push_tag(TypeTag::RustBorrow);
self.push_str(class_name);
}
#[doc(hidden)]
pub fn rust_value_class_name<T: EncodeTypeDef + ?Sized>() -> Option<alloc::string::String> {
let def = TypeDef::of::<T>();
let bytes = def.bytes();
if bytes.first().copied() != Some(TypeTag::RustValue as u8) {
return None;
}
let len_bytes = bytes.get(1..5)?;
let len = u32::from_le_bytes(len_bytes.try_into().ok()?) as usize;
let name_bytes = bytes.get(5..5 + len)?;
core::str::from_utf8(name_bytes).ok().map(Into::into)
}
#[doc(hidden)]
pub fn u8_clamped(&mut self) {
self.push_tag(TypeTag::U8Clamped);
}
pub fn mut_array<T: EncodeTypeDef + ?Sized>(&mut self) {
self.push_tag(TypeTag::MutArray);
self.push_tag(TypeTag::Array);
T::encode_type_def(self);
}
pub fn mut_u8_clamped(&mut self) {
self.push_tag(TypeTag::MutArray);
self.push_tag(TypeTag::U8Clamped);
}
pub fn string_enum(&mut self, variants: &[&str]) {
self.push_tag(TypeTag::StringEnum);
self.push_u8(u8::try_from(variants.len()).expect("too many string enum variants"));
for variant in variants {
self.push_str(variant);
}
}
pub fn numeric_enum(&mut self, signed: bool, values: &[u32]) {
self.push_tag(TypeTag::NumericEnum);
self.push_u8(signed as u8);
self.push_u8(u8::try_from(values.len()).expect("too many numeric enum variants"));
for value in values {
self.bytes.extend_from_slice(&value.to_le_bytes());
}
}
#[doc(hidden)]
pub fn dynamic_union(
&mut self,
variant_count: usize,
encode_variants: impl FnOnce(&mut TypeDef),
) {
self.push_tag(TypeTag::DynamicUnion);
self.push_u8(u8::try_from(variant_count).expect("too many dynamic union variants"));
encode_variants(self);
}
#[doc(hidden)]
pub fn dynamic_union_string_variant(&mut self, value: &str) {
self.push_u8(0);
self.push_str(value);
}
#[doc(hidden)]
pub fn dynamic_union_type_variant<T: EncodeTypeDef>(&mut self) {
self.push_u8(1);
T::encode_type_def(self);
}
#[doc(hidden)]
pub fn callback<Signature: EncodeTypeDef + ?Sized>(&mut self) {
self.push_tag(TypeTag::Callback);
Signature::encode_type_def(self);
}
#[doc(hidden)]
pub fn callback_with_signature(
&mut self,
arg_count: u8,
encode_args_and_return: impl FnOnce(&mut TypeDef),
) {
self.push_tag(TypeTag::Callback);
self.push_u8(arg_count);
encode_args_and_return(self);
}
fn push_tag(&mut self, tag: TypeTag) {
self.push_u8(tag as u8);
}
fn push_u8(&mut self, value: u8) {
self.bytes.push(value);
}
fn push_str(&mut self, value: &str) {
self.bytes
.extend_from_slice(&(value.len() as u32).to_le_bytes());
self.bytes.extend_from_slice(value.as_bytes());
}
}
pub trait EncodeTypeDef {
fn encode_type_def(type_def: &mut TypeDef);
}
impl EncodeTypeDef for () {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Undefined);
}
}
impl BinaryEncode for () {
fn encode(self, _encoder: &mut EncodedData) {}
}
impl BinaryDecode for () {
fn decode(_decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(())
}
}
macro_rules! impl_num {
($ty:ty, $tag:ident, $push:ident, $take:ident) => {
impl EncodeTypeDef for $ty {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::$tag);
}
}
impl BinaryEncode for $ty {
fn encode(self, encoder: &mut EncodedData) {
encoder.$push(self as _);
}
}
impl BinaryDecode for $ty {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(decoder.$take()? as $ty)
}
}
};
}
impl EncodeTypeDef for bool {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Bool);
}
}
impl BinaryEncode for bool {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u8(if self { 1 } else { 0 });
}
}
impl BinaryDecode for bool {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(decoder.take_u8()? != 0)
}
}
impl EncodeTypeDef for char {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Char);
}
}
impl BinaryEncode for char {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self as u32);
}
}
impl BinaryDecode for char {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
let cp = decoder.take_u32()?;
char::from_u32(cp).ok_or_else(|| {
DecodeError::custom(alloc::format!(
"expected a valid Unicode scalar value, found {cp}"
))
})
}
}
impl_num!(u8, U8, push_u8, take_u8);
impl_num!(u16, U16, push_u16, take_u16);
impl_num!(u32, U32, push_u32, take_u32);
impl_num!(u64, U64, push_u64, take_u64);
impl_num!(u128, U128, push_u128, take_u128);
impl_num!(i8, I8, push_u8, take_u8);
impl_num!(i16, I16, push_u16, take_u16);
impl_num!(i32, I32, push_u32, take_u32);
impl_num!(i64, I64, push_u64, take_u64);
impl_num!(i128, I128, push_u128, take_u128);
impl EncodeTypeDef for f32 {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::F32);
}
}
impl BinaryEncode for f32 {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.to_bits());
}
}
impl BinaryDecode for f32 {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(f32::from_bits(decoder.take_u32()?))
}
}
impl EncodeTypeDef for f64 {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::F64);
}
}
impl BinaryEncode for f64 {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u64(self.to_bits());
}
}
impl BinaryDecode for f64 {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(f64::from_bits(decoder.take_u64()?))
}
}
impl EncodeTypeDef for usize {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Usize);
}
}
impl BinaryEncode for usize {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u64(self as u64);
}
}
impl BinaryDecode for usize {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(decoder.take_u64()? as usize)
}
}
impl EncodeTypeDef for isize {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Isize);
}
}
impl BinaryEncode for isize {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u64(self as u64);
}
}
impl BinaryDecode for isize {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(decoder.take_u64()? as isize)
}
}
impl EncodeTypeDef for str {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::String);
}
}
impl EncodeTypeDef for &str {
fn encode_type_def(type_def: &mut TypeDef) {
str::encode_type_def(type_def);
}
}
impl<T: JsRefEncode + ?Sized> EncodeTypeDef for &T {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.borrowed_ref();
}
}
impl BinaryEncode for &str {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_str(self);
}
}
impl<T: JsRefEncode + ?Sized> BinaryEncode for &T {
fn encode(self, encoder: &mut EncodedData) {
self.js_ref().raw().encode(encoder);
}
}
impl EncodeTypeDef for String {
fn encode_type_def(type_def: &mut TypeDef) {
str::encode_type_def(type_def);
}
}
impl BinaryEncode for String {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_str(&self);
}
}
impl BinaryDecode for String {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(decoder.take_str()?.to_string())
}
}
impl<T: EncodeTypeDef> EncodeTypeDef for Option<T> {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Option);
T::encode_type_def(type_def);
}
}
impl<T: BinaryDecode> BinaryDecode for Option<T> {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
if decoder.take_u8()? != 0 {
Ok(Some(T::decode(decoder)?))
} else {
Ok(None)
}
}
}
impl<T: BinaryEncode> BinaryEncode for Option<T> {
fn encode(self, encoder: &mut EncodedData) {
match self {
Some(value) => {
encoder.push_u8(1);
value.encode(encoder);
}
None => encoder.push_u8(0),
}
}
}
impl<T: EncodeTypeDef, E: EncodeTypeDef> EncodeTypeDef for Result<T, E> {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Result);
T::encode_type_def(type_def);
E::encode_type_def(type_def);
}
}
impl<T: BinaryEncode, E: BinaryEncode> BinaryEncode for Result<T, E> {
fn encode(self, encoder: &mut EncodedData) {
match self {
Ok(value) => {
encoder.push_u8(1);
value.encode(encoder);
}
Err(error) => {
encoder.push_u8(0);
error.encode(encoder);
}
}
}
}
impl<T: BinaryDecode, E: BinaryDecode> BinaryDecode for Result<T, E> {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
if decoder.take_u8()? != 0 {
Ok(Ok(T::decode(decoder)?))
} else {
Ok(Err(E::decode(decoder)?))
}
}
}
pub struct ThrowingResult<T, E>(pub Result<T, E>);
impl<T: EncodeTypeDef, E: EncodeTypeDef> EncodeTypeDef for ThrowingResult<T, E> {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::ThrowingResult);
T::encode_type_def(type_def);
E::encode_type_def(type_def);
}
}
impl<T: BinaryEncode, E: BinaryEncode> BinaryEncode for ThrowingResult<T, E> {
fn encode(self, encoder: &mut EncodedData) {
self.0.encode(encoder);
}
}
impl<T: EncodeTypeDef> EncodeTypeDef for Vec<T> {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Array);
T::encode_type_def(type_def);
}
}
impl<T: EncodeTypeDef> EncodeTypeDef for &[T] {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Array);
T::encode_type_def(type_def);
}
}
impl<T: EncodeTypeDef> EncodeTypeDef for &mut [T] {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.mut_array::<T>();
}
}
impl<T: EncodeTypeDef> EncodeTypeDef for Box<[T]> {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_tag(TypeTag::Array);
T::encode_type_def(type_def);
}
}
pub struct MutSliceArg<T> {
buffer: Vec<T>,
}
impl<T: EncodeTypeDef> EncodeTypeDef for MutSliceArg<T> {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.mut_array::<T>();
}
}
impl<T: BinaryDecode> BinaryDecode for MutSliceArg<T> {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(MutSliceArg {
buffer: Vec::<T>::decode(decoder)?,
})
}
}
impl<T> MutSliceArg<T> {
pub(crate) fn as_mut_slice(&mut self) -> &mut [T] {
self.buffer.as_mut_slice()
}
pub(crate) fn write_back(self, encoder: &mut EncodedData)
where
T: BinaryEncode,
{
encoder.push_u32(self.buffer.len() as u32);
for val in self.buffer {
val.encode(encoder);
}
}
}
impl<T> core::ops::Deref for MutSliceArg<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.buffer.as_slice()
}
}
impl<T> core::ops::DerefMut for MutSliceArg<T> {
fn deref_mut(&mut self) -> &mut [T] {
self.buffer.as_mut_slice()
}
}
impl<T: BinaryEncode> BinaryEncode for Box<[T]> {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self.into_vec() {
val.encode(encoder);
}
}
}
impl<T: BinaryEncode> BinaryEncode for Vec<T> {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self {
val.encode(encoder);
}
}
}
impl<T: BinaryDecode> BinaryDecode for Vec<T> {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
let len = decoder.take_u32()? as usize;
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
let item = T::decode(decoder)
.map_err(|_| DecodeError::custom("array contains a value of the wrong type"))?;
vec.push(item);
}
Ok(vec)
}
}
impl<T: BinaryDecode> BinaryDecode for Box<[T]> {
fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
Ok(Vec::<T>::decode(decoder)?.into_boxed_slice())
}
}
macro_rules! ref_encode_via_clone {
($($ty:ty),* $(,)?) => {
$(
impl EncodeTypeDef for &$ty {
fn encode_type_def(type_def: &mut TypeDef) {
<$ty as EncodeTypeDef>::encode_type_def(type_def);
}
}
impl BinaryEncode for &$ty {
fn encode(self, encoder: &mut EncodedData) {
self.clone().encode(encoder);
}
}
)*
};
}
ref_encode_via_clone!(
bool, char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64, usize, isize, String,
);
fn register_slice_write_back<T: BinaryDecode + 'static>(slice: &mut [T]) {
let raw = slice as *mut [T];
crate::batch::push_write_back(Box::new(move |decoder: &mut DecodedData| {
let updated = Vec::<T>::decode(decoder).expect("failed to decode &mut [T] write-back");
let target = unsafe { &mut *raw };
for (dst, src) in target.iter_mut().zip(updated) {
*dst = src;
}
}));
}
macro_rules! slice_encode_via_copy {
($($ty:ty),* $(,)?) => {
$(
impl BinaryEncode for &[$ty] {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self {
(*val).encode(encoder);
}
}
}
impl BinaryEncode for &mut [$ty] {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self.iter() {
(*val).encode(encoder);
}
register_slice_write_back(self);
}
}
)*
};
}
slice_encode_via_copy!(
bool, char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64, usize, isize
);
impl BinaryEncode for &[String] {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self {
val.clone().encode(encoder);
}
}
}
impl BinaryEncode for &mut [String] {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self.iter() {
val.clone().encode(encoder);
}
register_slice_write_back(self);
}
}
impl<T: JsRefEncode> BinaryEncode for &[T] {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self {
val.js_ref().raw().encode(encoder);
}
}
}
impl<T: JsRefEncode + BinaryDecode + 'static> BinaryEncode for &mut [T] {
fn encode(self, encoder: &mut EncodedData) {
encoder.push_u32(self.len() as u32);
for val in self.iter() {
val.js_ref().raw().encode(encoder);
}
register_slice_write_back(self);
}
}
macro_rules! impl_fn_type_def {
(0,) => {
impl<R: EncodeTypeDef> EncodeTypeDef for fn() -> R {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_u8(0);
R::encode_type_def(type_def);
}
}
};
($n:expr, $($T:ident),+) => {
impl<$($T: EncodeTypeDef,)+ R: EncodeTypeDef> EncodeTypeDef for fn($($T),+) -> R {
fn encode_type_def(type_def: &mut TypeDef) {
type_def.push_u8($n);
$($T::encode_type_def(type_def);)+
R::encode_type_def(type_def);
}
}
};
}
impl_fn_type_def!(0,);
impl_fn_type_def!(1, T1);
impl_fn_type_def!(2, T1, T2);
impl_fn_type_def!(3, T1, T2, T3);
impl_fn_type_def!(4, T1, T2, T3, T4);
impl_fn_type_def!(5, T1, T2, T3, T4, T5);
impl_fn_type_def!(6, T1, T2, T3, T4, T5, T6);
impl_fn_type_def!(7, T1, T2, T3, T4, T5, T6, T7);
impl_fn_type_def!(8, T1, T2, T3, T4, T5, T6, T7, T8);
impl_fn_type_def!(9, T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_fn_type_def!(10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_fn_type_def!(11, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_fn_type_def!(12, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_fn_type_def!(13, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
impl_fn_type_def!(
14, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
);
impl_fn_type_def!(
15, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
);
impl_fn_type_def!(
16, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16
);
impl_fn_type_def!(
17, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17
);
impl_fn_type_def!(
18, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18
);
impl_fn_type_def!(
19, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19
);
impl_fn_type_def!(
20, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20
);
impl_fn_type_def!(
21, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21
);
impl_fn_type_def!(
22, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22
);
impl_fn_type_def!(
23, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23
);
impl_fn_type_def!(
24, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24
);
impl_fn_type_def!(
25, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25
);
impl_fn_type_def!(
26, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25, T26
);
impl_fn_type_def!(
27, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25, T26, T27
);
impl_fn_type_def!(
28, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25, T26, T27, T28
);
impl_fn_type_def!(
29, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25, T26, T27, T28, T29
);
impl_fn_type_def!(
30, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30
);
impl_fn_type_def!(
31, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31
);
impl_fn_type_def!(
32, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20,
T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32
);