use crate::ModuleType;
use id_arena::{Arena, Id};
use indexmap::{IndexMap, IndexSet};
use std::{
fmt,
ops::{Index, IndexMut},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DefinedTypeId(Id<DefinedType>);
#[cfg(feature = "serde")]
impl serde::Serialize for DefinedTypeId {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.index().serialize(serializer)
}
}
impl fmt::Display for DefinedTypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.index())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ResourceId(Id<Resource>);
#[cfg(feature = "serde")]
impl serde::Serialize for ResourceId {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.index().serialize(serializer)
}
}
impl fmt::Display for ResourceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.index())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FuncTypeId(Id<FuncType>);
#[cfg(feature = "serde")]
impl serde::Serialize for FuncTypeId {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.index().serialize(serializer)
}
}
impl fmt::Display for FuncTypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.index())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InterfaceId(Id<Interface>);
#[cfg(feature = "serde")]
impl serde::Serialize for InterfaceId {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.index().serialize(serializer)
}
}
impl fmt::Display for InterfaceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.index())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct WorldId(Id<World>);
#[cfg(feature = "serde")]
impl serde::Serialize for WorldId {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.index().serialize(serializer)
}
}
impl fmt::Display for WorldId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.index())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ModuleTypeId(Id<ModuleType>);
#[cfg(feature = "serde")]
impl serde::Serialize for ModuleId {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.0.index().serialize(serializer)
}
}
impl fmt::Display for ModuleTypeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.index())
}
}
#[cfg(feature = "serde")]
fn serialize_arena<T, S>(arena: &Arena<T>, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
T: serde::Serialize,
{
use serde::ser::SerializeSeq;
let mut s = serializer.serialize_seq(Some(arena.len()))?;
for (_, e) in arena.iter() {
s.serialize_element(e)?;
}
s.end()
}
#[derive(Default, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Types {
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
defined: Arena<DefinedType>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
resources: Arena<Resource>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
funcs: Arena<FuncType>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
interfaces: Arena<Interface>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
worlds: Arena<World>,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_arena"))]
modules: Arena<ModuleType>,
}
impl Types {
pub fn new() -> Self {
Self::default()
}
pub fn defined_types(&self) -> impl Iterator<Item = &DefinedType> {
self.defined.iter().map(|(_, t)| t)
}
pub fn resources(&self) -> impl Iterator<Item = &Resource> {
self.resources.iter().map(|(_, t)| t)
}
pub fn func_types(&self) -> impl Iterator<Item = &FuncType> {
self.funcs.iter().map(|(_, t)| t)
}
pub fn interfaces(&self) -> impl Iterator<Item = &Interface> {
self.interfaces.iter().map(|(_, t)| t)
}
pub fn worlds(&self) -> impl Iterator<Item = &World> {
self.worlds.iter().map(|(_, t)| t)
}
pub fn modules(&self) -> impl Iterator<Item = &ModuleType> {
self.modules.iter().map(|(_, t)| t)
}
pub fn add_defined_type(&mut self, ty: DefinedType) -> DefinedTypeId {
DefinedTypeId(self.defined.alloc(ty))
}
pub fn add_resource(&mut self, resource: Resource) -> ResourceId {
ResourceId(self.resources.alloc(resource))
}
pub fn add_func_type(&mut self, func: FuncType) -> FuncTypeId {
FuncTypeId(self.funcs.alloc(func))
}
pub fn add_interface(&mut self, interface: Interface) -> InterfaceId {
InterfaceId(self.interfaces.alloc(interface))
}
pub fn add_world(&mut self, world: World) -> WorldId {
WorldId(self.worlds.alloc(world))
}
pub fn add_module_type(&mut self, module: ModuleType) -> ModuleTypeId {
ModuleTypeId(self.modules.alloc(module))
}
pub fn contains(&self, ty: Type) -> bool {
match ty {
Type::Resource(id)
| Type::Value(ValueType::Borrow(id))
| Type::Value(ValueType::Own(id)) => self.resources.get(id.0).is_some(),
Type::Func(id) => self.funcs.get(id.0).is_some(),
Type::Value(ValueType::Primitive(_)) => true,
Type::Value(ValueType::Defined(id)) => self.defined.get(id.0).is_some(),
Type::Interface(id) => self.interfaces.get(id.0).is_some(),
Type::World(id) => self.worlds.get(id.0).is_some(),
Type::Module(id) => self.modules.get(id.0).is_some(),
}
}
pub fn resolve_value_type(&self, mut ty: ValueType) -> ValueType {
loop {
match ty {
ValueType::Defined(id) => match self[id] {
DefinedType::Alias(aliased) => ty = aliased,
_ => return ty,
},
_ => return ty,
}
}
}
pub fn resolve_resource(&self, mut id: ResourceId) -> ResourceId {
while let Some(alias) = &self[id].alias {
id = alias.source;
}
id
}
}
impl Index<DefinedTypeId> for Types {
type Output = DefinedType;
fn index(&self, id: DefinedTypeId) -> &Self::Output {
&self.defined[id.0]
}
}
impl Index<ResourceId> for Types {
type Output = Resource;
fn index(&self, id: ResourceId) -> &Self::Output {
&self.resources[id.0]
}
}
impl Index<FuncTypeId> for Types {
type Output = FuncType;
fn index(&self, id: FuncTypeId) -> &Self::Output {
&self.funcs[id.0]
}
}
impl Index<InterfaceId> for Types {
type Output = Interface;
fn index(&self, id: InterfaceId) -> &Self::Output {
&self.interfaces[id.0]
}
}
impl Index<WorldId> for Types {
type Output = World;
fn index(&self, id: WorldId) -> &Self::Output {
&self.worlds[id.0]
}
}
impl Index<ModuleTypeId> for Types {
type Output = ModuleType;
fn index(&self, id: ModuleTypeId) -> &Self::Output {
&self.modules[id.0]
}
}
impl IndexMut<DefinedTypeId> for Types {
fn index_mut(&mut self, id: DefinedTypeId) -> &mut Self::Output {
&mut self.defined[id.0]
}
}
impl IndexMut<ResourceId> for Types {
fn index_mut(&mut self, id: ResourceId) -> &mut Self::Output {
&mut self.resources[id.0]
}
}
impl IndexMut<FuncTypeId> for Types {
fn index_mut(&mut self, id: FuncTypeId) -> &mut Self::Output {
&mut self.funcs[id.0]
}
}
impl IndexMut<InterfaceId> for Types {
fn index_mut(&mut self, id: InterfaceId) -> &mut Self::Output {
&mut self.interfaces[id.0]
}
}
impl IndexMut<WorldId> for Types {
fn index_mut(&mut self, id: WorldId) -> &mut Self::Output {
&mut self.worlds[id.0]
}
}
impl IndexMut<ModuleTypeId> for Types {
fn index_mut(&mut self, id: ModuleTypeId) -> &mut Self::Output {
&mut self.modules[id.0]
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub enum ItemKind {
Type(Type),
Func(FuncTypeId),
Instance(InterfaceId),
Component(WorldId),
Module(ModuleTypeId),
Value(ValueType),
}
impl ItemKind {
pub fn ty(&self) -> Type {
match self {
ItemKind::Type(ty) => *ty,
ItemKind::Func(id) => Type::Func(*id),
ItemKind::Instance(id) => Type::Interface(*id),
ItemKind::Component(id) => Type::World(*id),
ItemKind::Module(id) => Type::Module(*id),
ItemKind::Value(ty) => Type::Value(*ty),
}
}
pub fn desc(&self, types: &Types) -> &'static str {
match self {
ItemKind::Func(_) => "function",
ItemKind::Type(ty) => ty.desc(types),
ItemKind::Instance(_) => "instance",
ItemKind::Component(_) => "component",
ItemKind::Module(_) => "module",
ItemKind::Value(_) => "value",
}
}
pub fn promote(&self) -> Self {
match *self {
ItemKind::Type(Type::Func(id)) => ItemKind::Func(id),
ItemKind::Type(Type::Interface(id)) => ItemKind::Instance(id),
ItemKind::Type(Type::World(id)) => ItemKind::Component(id),
kind => kind,
}
}
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
) -> Result<(), E> {
match self {
ItemKind::Type(ty) => ty._visit_defined_types(types, visitor, false),
ItemKind::Func(id) => types[*id]._visit_defined_types(types, visitor),
ItemKind::Instance(id) => types[*id]._visit_defined_types(types, visitor),
ItemKind::Component(id) => types[*id]._visit_defined_types(types, visitor),
ItemKind::Module(_) => Ok(()),
ItemKind::Value(ty) => ty._visit_defined_types(types, visitor, false),
}
}
}
impl From<ItemKind> for wasm_encoder::ComponentExportKind {
fn from(value: ItemKind) -> Self {
match value {
ItemKind::Type(_) => Self::Type,
ItemKind::Func(_) => Self::Func,
ItemKind::Instance(_) => Self::Instance,
ItemKind::Component(_) => Self::Component,
ItemKind::Module(_) => Self::Module,
ItemKind::Value(_) => Self::Value,
}
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub enum Type {
Resource(ResourceId),
Func(FuncTypeId),
Value(ValueType),
Interface(InterfaceId),
World(WorldId),
Module(ModuleTypeId),
}
impl Type {
pub fn desc(&self, types: &Types) -> &'static str {
match self {
Type::Resource(_) => "resource",
Type::Func(_) => "function type",
Type::Value(ty) => ty.desc(types),
Type::Interface(_) => "interface",
Type::World(_) => "world",
Type::Module(_) => "module type",
}
}
pub fn visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
) -> Result<(), E> {
self._visit_defined_types(types, visitor, true)
}
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
recurse: bool,
) -> Result<(), E> {
match self {
Type::Module(_) | Type::Resource(_) => Ok(()),
Type::Func(id) => types[*id]._visit_defined_types(types, visitor),
Type::Value(ty) => ty._visit_defined_types(types, visitor, recurse),
Type::Interface(id) => types[*id]._visit_defined_types(types, visitor),
Type::World(id) => types[*id]._visit_defined_types(types, visitor),
}
}
}
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub enum PrimitiveType {
U8,
S8,
U16,
S16,
U32,
S32,
U64,
S64,
F32,
F64,
Char,
Bool,
String,
}
impl PrimitiveType {
pub fn desc(&self) -> &'static str {
match self {
Self::U8 => "u8",
Self::S8 => "s8",
Self::U16 => "u16",
Self::S16 => "s16",
Self::U32 => "u32",
Self::S32 => "s32",
Self::U64 => "u64",
Self::S64 => "s64",
Self::F32 => "f32",
Self::F64 => "f64",
Self::Char => "char",
Self::Bool => "bool",
Self::String => "string",
}
}
}
impl From<wasmparser::PrimitiveValType> for PrimitiveType {
fn from(value: wasmparser::PrimitiveValType) -> Self {
match value {
wasmparser::PrimitiveValType::Bool => Self::Bool,
wasmparser::PrimitiveValType::S8 => Self::S8,
wasmparser::PrimitiveValType::U8 => Self::U8,
wasmparser::PrimitiveValType::S16 => Self::S16,
wasmparser::PrimitiveValType::U16 => Self::U16,
wasmparser::PrimitiveValType::S32 => Self::S32,
wasmparser::PrimitiveValType::U32 => Self::U32,
wasmparser::PrimitiveValType::S64 => Self::S64,
wasmparser::PrimitiveValType::U64 => Self::U64,
wasmparser::PrimitiveValType::F32 => Self::F32,
wasmparser::PrimitiveValType::F64 => Self::F64,
wasmparser::PrimitiveValType::Char => Self::Char,
wasmparser::PrimitiveValType::String => Self::String,
}
}
}
impl From<PrimitiveType> for wasm_encoder::PrimitiveValType {
fn from(value: PrimitiveType) -> Self {
match value {
PrimitiveType::U8 => Self::U8,
PrimitiveType::S8 => Self::S8,
PrimitiveType::U16 => Self::U16,
PrimitiveType::S16 => Self::S16,
PrimitiveType::U32 => Self::U32,
PrimitiveType::S32 => Self::S32,
PrimitiveType::U64 => Self::U64,
PrimitiveType::S64 => Self::S64,
PrimitiveType::F32 => Self::F32,
PrimitiveType::F64 => Self::F64,
PrimitiveType::Char => Self::Char,
PrimitiveType::Bool => Self::Bool,
PrimitiveType::String => Self::String,
}
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
pub enum ValueType {
Primitive(PrimitiveType),
Borrow(ResourceId),
Own(ResourceId),
Defined(DefinedTypeId),
}
impl ValueType {
pub fn contains_borrow(&self, types: &Types) -> bool {
match self {
ValueType::Primitive(_) | ValueType::Own(_) => false,
ValueType::Borrow(_) => true,
ValueType::Defined(id) => types[*id].contains_borrow(types),
}
}
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
recurse: bool,
) -> Result<(), E> {
match self {
ValueType::Primitive(_) | ValueType::Borrow(_) | ValueType::Own(_) => Ok(()),
ValueType::Defined(id) => {
visitor(types, *id)?;
if recurse {
types[*id]._visit_defined_types(types, visitor)?;
}
Ok(())
}
}
}
pub fn desc(&self, types: &Types) -> &'static str {
match self {
Self::Primitive(ty) => ty.desc(),
Self::Borrow(_) => "borrow",
Self::Own(_) => "own",
Self::Defined(id) => types[*id].desc(types),
}
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for ValueType {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Primitive(ty) => ty.serialize(serializer),
Self::Borrow(id) => format!("borrow<{id}>", id = id.0.index()).serialize(serializer),
Self::Own(id) => format!("own<{id}>", id = id.0.index()).serialize(serializer),
Self::Defined { id, .. } => id.serialize(serializer),
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub enum DefinedType {
Tuple(Vec<ValueType>),
List(ValueType),
Option(ValueType),
Result {
ok: Option<ValueType>,
err: Option<ValueType>,
},
Variant(Variant),
Record(Record),
Flags(Flags),
Enum(Enum),
Alias(ValueType),
}
impl DefinedType {
pub fn contains_borrow(&self, types: &Types) -> bool {
match self {
Self::Tuple(tys) => tys.iter().any(|ty| ty.contains_borrow(types)),
Self::List(ty) => ty.contains_borrow(types),
Self::Option(ty) => ty.contains_borrow(types),
Self::Result { ok, err } => {
ok.map(|ty| ty.contains_borrow(types)).unwrap_or(false)
|| err.map(|ty| ty.contains_borrow(types)).unwrap_or(false)
}
Self::Variant(v) => v
.cases
.values()
.any(|ty| ty.map(|ty| ty.contains_borrow(types)).unwrap_or(false)),
Self::Record(r) => r.fields.iter().any(|(_, ty)| ty.contains_borrow(types)),
Self::Flags(_) => false,
Self::Enum(_) => false,
Self::Alias(ty) => ty.contains_borrow(types),
}
}
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
) -> Result<(), E> {
match self {
DefinedType::Tuple(tys) => {
for ty in tys {
ty._visit_defined_types(types, visitor, false)?;
}
Ok(())
}
DefinedType::List(ty) | DefinedType::Option(ty) => {
ty._visit_defined_types(types, visitor, false)
}
DefinedType::Result { ok, err } => {
if let Some(ty) = ok.as_ref() {
ty._visit_defined_types(types, visitor, false)?;
}
if let Some(ty) = err.as_ref() {
ty._visit_defined_types(types, visitor, false)?;
}
Ok(())
}
DefinedType::Variant(v) => {
for ty in v.cases.values().filter_map(Option::as_ref) {
ty._visit_defined_types(types, visitor, false)?;
}
Ok(())
}
DefinedType::Record(r) => {
for (_, ty) in &r.fields {
ty._visit_defined_types(types, visitor, false)?
}
Ok(())
}
DefinedType::Flags(_) | DefinedType::Enum(_) | DefinedType::Alias(_) => Ok(()),
}
}
pub fn desc(&self, types: &Types) -> &'static str {
match self {
Self::Tuple(_) => "tuple",
Self::List(_) => "list",
Self::Option(_) => "option",
Self::Result { .. } => "result",
Self::Variant(_) => "variant",
Self::Record(_) => "record",
Self::Flags(_) => "flags",
Self::Enum(_) => "enum",
Self::Alias(ty) => ty.desc(types),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub enum FuncKind {
Free,
Method,
Static,
Constructor,
}
impl fmt::Display for FuncKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FuncKind::Free => write!(f, "function"),
FuncKind::Method => write!(f, "method"),
FuncKind::Static => write!(f, "static method"),
FuncKind::Constructor => write!(f, "constructor"),
}
}
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct ResourceAlias {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub owner: Option<InterfaceId>,
pub source: ResourceId,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Resource {
pub name: String,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub alias: Option<ResourceAlias>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Variant {
pub cases: IndexMap<String, Option<ValueType>>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Record {
pub fields: IndexMap<String, ValueType>,
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Flags(pub IndexSet<String>);
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Enum(pub IndexSet<String>);
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct FuncType {
pub params: IndexMap<String, ValueType>,
pub results: Option<FuncResult>,
}
impl FuncType {
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
) -> Result<(), E> {
for ty in self.params.values() {
ty._visit_defined_types(types, visitor, false)?;
}
if let Some(results) = self.results.as_ref() {
results._visit_defined_types(types, visitor)?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub enum FuncResult {
Scalar(ValueType),
List(IndexMap<String, ValueType>),
}
impl FuncResult {
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
) -> Result<(), E> {
match self {
FuncResult::Scalar(ty) => ty._visit_defined_types(types, visitor, false),
FuncResult::List(tys) => {
for ty in tys.values() {
ty._visit_defined_types(types, visitor, false)?;
}
Ok(())
}
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct UsedType {
pub interface: InterfaceId,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
}
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Interface {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub id: Option<String>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "IndexMap::is_empty"))]
pub uses: IndexMap<String, UsedType>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "IndexMap::is_empty"))]
pub exports: IndexMap<String, ItemKind>,
}
impl Interface {
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
) -> Result<(), E> {
for kind in self.exports.values() {
kind._visit_defined_types(types, visitor)?;
}
Ok(())
}
}
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct World {
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub id: Option<String>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "IndexMap::is_empty"))]
pub uses: IndexMap<String, UsedType>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "IndexMap::is_empty"))]
pub imports: IndexMap<String, ItemKind>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "IndexMap::is_empty"))]
pub exports: IndexMap<String, ItemKind>,
}
impl World {
fn _visit_defined_types<'a, E>(
&self,
types: &'a Types,
visitor: &mut impl FnMut(&'a Types, DefinedTypeId) -> Result<(), E>,
) -> Result<(), E> {
for kind in self.imports.values() {
kind._visit_defined_types(types, visitor)?;
}
for kind in self.exports.values() {
kind._visit_defined_types(types, visitor)?;
}
Ok(())
}
pub fn implicit_imported_interfaces<'a>(
&'a self,
types: &'a Types,
) -> IndexMap<&str, ItemKind> {
let mut interfaces = IndexMap::new();
let mut add_interface_for_used_type = |used_item: &UsedType| {
let used_interface_id = used_item.interface;
let used_interface_name = types[used_interface_id].id.as_deref().unwrap();
interfaces.insert(used_interface_name, ItemKind::Instance(used_interface_id));
};
for (_, used_type) in self.uses.iter() {
add_interface_for_used_type(used_type);
}
for (_, import) in self.imports.iter() {
if let ItemKind::Instance(interface_id) = import {
let import = &types[*interface_id];
for (_, used_item) in &import.uses {
add_interface_for_used_type(used_item);
}
}
}
interfaces
}
}
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
pub enum ExternKind {
Import,
Export,
}
impl fmt::Display for ExternKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Import => write!(f, "import"),
Self::Export => write!(f, "export"),
}
}
}