use std::{io, fmt}; use super::{ Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint1, CountedList, CountedListWriter }; /// Type definition in types section. Currently can be only of the function type. #[derive(Debug, PartialEq, Clone)] pub enum Type { /// Function type. Function(FunctionType), } impl Deserialize for Type { type Error = Error; fn deserialize(reader: &mut R) -> Result { Ok(Type::Function(FunctionType::deserialize(reader)?)) } } impl Serialize for Type { type Error = Error; fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { match self { Type::Function(fn_type) => fn_type.serialize(writer) } } } /// Value type. #[derive(Clone, Copy, PartialEq, Debug)] pub enum ValueType { /// 32-bit signed integer I32, /// 64-bit signed integer I64, /// 32-bit float F32, /// 64-bit float F64, } impl Deserialize for ValueType { type Error = Error; fn deserialize(reader: &mut R) -> Result { let val = VarInt7::deserialize(reader)?; match val.into() { -0x01 => Ok(ValueType::I32), -0x02 => Ok(ValueType::I64), -0x03 => Ok(ValueType::F32), -0x04 => Ok(ValueType::F64), _ => Err(Error::UnknownValueType(val.into())), } } } impl Serialize for ValueType { type Error = Error; fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { let val: VarInt7 = match self { ValueType::I32 => -0x01, ValueType::I64 => -0x02, ValueType::F32 => -0x03, ValueType::F64 => -0x04, }.into(); val.serialize(writer)?; Ok(()) } } impl fmt::Display for ValueType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ValueType::I32 => write!(f, "i32"), ValueType::I64 => write!(f, "i64"), ValueType::F32 => write!(f, "f32"), ValueType::F64 => write!(f, "f64"), } } } /// Block type which is basically `ValueType` + NoResult (to define blocks that have no return type) #[derive(Clone, Copy, PartialEq, Debug)] pub enum BlockType { /// Value-type specified block type Value(ValueType), /// No specified block type NoResult, } impl Deserialize for BlockType { type Error = Error; fn deserialize(reader: &mut R) -> Result { let val = VarInt7::deserialize(reader)?; match val.into() { -0x01 => Ok(BlockType::Value(ValueType::I32)), -0x02 => Ok(BlockType::Value(ValueType::I64)), -0x03 => Ok(BlockType::Value(ValueType::F32)), -0x04 => Ok(BlockType::Value(ValueType::F64)), -0x40 => Ok(BlockType::NoResult), _ => Err(Error::UnknownValueType(val.into())), } } } impl Serialize for BlockType { type Error = Error; fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { let val: VarInt7 = match self { BlockType::NoResult => -0x40i8, BlockType::Value(ValueType::I32) => -0x01, BlockType::Value(ValueType::I64) => -0x02, BlockType::Value(ValueType::F32) => -0x03, BlockType::Value(ValueType::F64) => -0x04, }.into(); val.serialize(writer)?; Ok(()) } } /// Function signature type. #[derive(Debug, Clone, PartialEq)] pub struct FunctionType { form: u8, params: Vec, return_type: Option, } impl Default for FunctionType { fn default() -> Self { FunctionType { form: 0x60, params: Vec::new(), return_type: None, } } } impl FunctionType { /// New function type given the signature in-params(`params`) and return type (`return_type`) pub fn new(params: Vec, return_type: Option) -> Self { FunctionType { params: params, return_type: return_type, ..Default::default() } } /// Function form (currently only valid value is `0x60`) pub fn form(&self) -> u8 { self.form } /// Parameters in the function signature. pub fn params(&self) -> &[ValueType] { &self.params } /// Mutable parameters in the function signature. pub fn params_mut(&mut self) -> &mut Vec { &mut self.params } /// Return type in the function signature, if any. pub fn return_type(&self) -> Option { self.return_type } /// Mutable type in the function signature, if any. pub fn return_type_mut(&mut self) -> &mut Option { &mut self.return_type } } impl Deserialize for FunctionType { type Error = Error; fn deserialize(reader: &mut R) -> Result { let form: u8 = VarUint7::deserialize(reader)?.into(); let params: Vec = CountedList::deserialize(reader)?.into_inner(); let has_return_type = VarUint1::deserialize(reader)?; let return_type = if has_return_type.into() { Some(ValueType::deserialize(reader)?) } else { None }; Ok(FunctionType { form: form, params: params, return_type: return_type, }) } } impl Serialize for FunctionType { type Error = Error; fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { VarUint7::from(self.form).serialize(writer)?; let data = self.params; let counted_list = CountedListWriter::( data.len(), data.into_iter().map(Into::into), ); counted_list.serialize(writer)?; if let Some(return_type) = self.return_type { VarUint1::from(true).serialize(writer)?; return_type.serialize(writer)?; } else { VarUint1::from(false).serialize(writer)?; } Ok(()) } } /// Table element type. #[derive(Clone, Copy, PartialEq, Debug)] pub enum TableElementType { /// A reference to a function with any signature. AnyFunc, } impl Deserialize for TableElementType { type Error = Error; fn deserialize(reader: &mut R) -> Result { let val = VarInt7::deserialize(reader)?; match val.into() { -0x10 => Ok(TableElementType::AnyFunc), _ => Err(Error::UnknownTableElementType(val.into())), } } } impl Serialize for TableElementType { type Error = Error; fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { let val: VarInt7 = match self { TableElementType::AnyFunc => 0x70, }.into(); val.serialize(writer)?; Ok(()) } }