use super::{
Deserialize, Error, Serialize, TableElementType, Uint8, ValueType, VarInt7, VarUint1,
VarUint32, VarUint7,
};
use crate::io;
use alloc::string::String;
const FLAG_HAS_MAX: u8 = 0x01;
#[cfg(feature = "atomics")]
const FLAG_SHARED: u8 = 0x02;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct GlobalType {
content_type: ValueType,
is_mutable: bool,
}
impl GlobalType {
pub fn new(content_type: ValueType, is_mutable: bool) -> Self {
GlobalType { content_type, is_mutable }
}
pub fn content_type(&self) -> ValueType {
self.content_type
}
pub fn is_mutable(&self) -> bool {
self.is_mutable
}
}
impl Deserialize for GlobalType {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let content_type = ValueType::deserialize(reader)?;
let is_mutable = VarUint1::deserialize(reader)?;
Ok(GlobalType { content_type, is_mutable: is_mutable.into() })
}
}
impl Serialize for GlobalType {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.content_type.serialize(writer)?;
VarUint1::from(self.is_mutable).serialize(writer)?;
Ok(())
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct TableType {
elem_type: TableElementType,
limits: ResizableLimits,
}
impl TableType {
pub fn new(min: u32, max: Option<u32>) -> Self {
TableType { elem_type: TableElementType::AnyFunc, limits: ResizableLimits::new(min, max) }
}
pub fn limits(&self) -> &ResizableLimits {
&self.limits
}
pub fn elem_type(&self) -> TableElementType {
self.elem_type
}
}
impl Deserialize for TableType {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let elem_type = TableElementType::deserialize(reader)?;
let limits = ResizableLimits::deserialize(reader)?;
Ok(TableType { elem_type, limits })
}
}
impl Serialize for TableType {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.elem_type.serialize(writer)?;
self.limits.serialize(writer)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct ResizableLimits {
initial: u32,
maximum: Option<u32>,
#[cfg(feature = "atomics")]
shared: bool,
}
impl ResizableLimits {
pub fn new(min: u32, max: Option<u32>) -> Self {
ResizableLimits {
initial: min,
maximum: max,
#[cfg(feature = "atomics")]
shared: false,
}
}
pub fn initial(&self) -> u32 {
self.initial
}
pub fn maximum(&self) -> Option<u32> {
self.maximum
}
#[cfg(feature = "atomics")]
pub fn shared(&self) -> bool {
self.shared
}
}
impl Deserialize for ResizableLimits {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let flags: u8 = Uint8::deserialize(reader)?.into();
match flags {
0x00 | 0x01 => {},
#[cfg(feature = "atomics")]
0x03 => {},
_ => return Err(Error::InvalidLimitsFlags(flags)),
}
let initial = VarUint32::deserialize(reader)?;
let maximum = if flags & FLAG_HAS_MAX != 0 {
Some(VarUint32::deserialize(reader)?.into())
} else {
None
};
Ok(ResizableLimits {
initial: initial.into(),
maximum,
#[cfg(feature = "atomics")]
shared: flags & FLAG_SHARED != 0,
})
}
}
impl Serialize for ResizableLimits {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
let mut flags: u8 = 0;
if self.maximum.is_some() {
flags |= FLAG_HAS_MAX;
}
#[cfg(feature = "atomics")]
{
if self.shared {
flags |= FLAG_SHARED;
}
}
Uint8::from(flags).serialize(writer)?;
VarUint32::from(self.initial).serialize(writer)?;
if let Some(max) = self.maximum {
VarUint32::from(max).serialize(writer)?;
}
Ok(())
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct MemoryType(ResizableLimits);
impl MemoryType {
pub fn new(min: u32, max: Option<u32>) -> Self {
let r = ResizableLimits::new(min, max);
MemoryType(r)
}
#[cfg(feature = "atomics")]
pub fn set_shared(&mut self, shared: bool) {
self.0.shared = shared;
}
pub fn limits(&self) -> &ResizableLimits {
&self.0
}
}
impl Deserialize for MemoryType {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
Ok(MemoryType(ResizableLimits::deserialize(reader)?))
}
}
impl Serialize for MemoryType {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.0.serialize(writer)
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum External {
Function(u32),
Table(TableType),
Memory(MemoryType),
Global(GlobalType),
}
impl Deserialize for External {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let kind = VarUint7::deserialize(reader)?;
match kind.into() {
0x00 => Ok(External::Function(VarUint32::deserialize(reader)?.into())),
0x01 => Ok(External::Table(TableType::deserialize(reader)?)),
0x02 => Ok(External::Memory(MemoryType::deserialize(reader)?)),
0x03 => Ok(External::Global(GlobalType::deserialize(reader)?)),
_ => Err(Error::UnknownExternalKind(kind.into())),
}
}
}
impl Serialize for External {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
use self::External::*;
match self {
Function(index) => {
VarUint7::from(0x00).serialize(writer)?;
VarUint32::from(index).serialize(writer)?;
},
Table(tt) => {
VarInt7::from(0x01).serialize(writer)?;
tt.serialize(writer)?;
},
Memory(mt) => {
VarInt7::from(0x02).serialize(writer)?;
mt.serialize(writer)?;
},
Global(gt) => {
VarInt7::from(0x03).serialize(writer)?;
gt.serialize(writer)?;
},
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ImportEntry {
module_str: String,
field_str: String,
external: External,
}
impl ImportEntry {
pub fn new(module_str: String, field_str: String, external: External) -> Self {
ImportEntry { module_str, field_str, external }
}
pub fn module(&self) -> &str {
&self.module_str
}
pub fn module_mut(&mut self) -> &mut String {
&mut self.module_str
}
pub fn field(&self) -> &str {
&self.field_str
}
pub fn field_mut(&mut self) -> &mut String {
&mut self.field_str
}
pub fn external(&self) -> &External {
&self.external
}
pub fn external_mut(&mut self) -> &mut External {
&mut self.external
}
}
impl Deserialize for ImportEntry {
type Error = Error;
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let module_str = String::deserialize(reader)?;
let field_str = String::deserialize(reader)?;
let external = External::deserialize(reader)?;
Ok(ImportEntry { module_str, field_str, external })
}
}
impl Serialize for ImportEntry {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
self.module_str.serialize(writer)?;
self.field_str.serialize(writer)?;
self.external.serialize(writer)
}
}