1#![no_std]
2
3extern crate alloc;
4
5#[cfg(feature = "std")]
6extern crate std;
7
8use crate::abi::AbiVariant;
9use alloc::format;
10use alloc::string::{String, ToString};
11use alloc::vec::Vec;
12use id_arena::{Arena, Id};
13use semver::Version;
14
15#[cfg(feature = "std")]
16pub type IndexMap<K, V> = indexmap::IndexMap<K, V, std::hash::RandomState>;
17#[cfg(feature = "std")]
18pub type IndexSet<T> = indexmap::IndexSet<T, std::hash::RandomState>;
19#[cfg(not(feature = "std"))]
20pub type IndexMap<K, V> = indexmap::IndexMap<K, V, hashbrown::DefaultHashBuilder>;
21#[cfg(not(feature = "std"))]
22pub type IndexSet<T> = indexmap::IndexSet<T, hashbrown::DefaultHashBuilder>;
23
24#[cfg(feature = "std")]
25pub(crate) use std::collections::{HashMap, HashSet};
26
27#[cfg(not(feature = "std"))]
28pub(crate) use hashbrown::{HashMap, HashSet};
29
30use alloc::borrow::Cow;
31use core::fmt;
32use core::hash::{Hash, Hasher};
33#[cfg(feature = "std")]
34use std::path::Path;
35
36#[cfg(feature = "decoding")]
37pub mod decoding;
38#[cfg(feature = "decoding")]
39mod metadata;
40#[cfg(feature = "decoding")]
41pub use metadata::PackageMetadata;
42
43pub mod abi;
44mod ast;
45pub use ast::error::*;
46pub use ast::lex::Span;
47pub use ast::{ItemName, SourceMap, SpanLocation};
48pub use ast::{ParsedUsePath, parse_use_path};
49mod sizealign;
50pub use sizealign::*;
51mod resolve;
52pub use resolve::error::*;
53pub use resolve::*;
54mod live;
55pub use live::{LiveTypes, TypeIdVisitor};
56
57#[cfg(feature = "serde")]
58use serde_derive::Serialize;
59#[cfg(feature = "serde")]
60mod serde_;
61#[cfg(feature = "serde")]
62use serde_::*;
63
64pub fn validate_id(s: &str) -> anyhow::Result<()> {
66 ast::validate_id(0, s)?;
67 Ok(())
68}
69
70#[cfg(feature = "std")]
83pub fn render_anyhow_error(err: &anyhow::Error, source_map: &SourceMap) -> String {
84 err.chain()
85 .map(|layer| {
86 if let Some(re) = layer.downcast_ref::<ResolveError>() {
87 re.render(source_map)
88 } else if let Some(pe) = layer.downcast_ref::<ParseError>() {
89 pe.render(source_map)
90 } else {
91 layer.to_string()
92 }
93 })
94 .collect::<Vec<_>>()
95 .join(": ")
96}
97
98pub type WorldId = Id<World>;
99pub type InterfaceId = Id<Interface>;
100pub type TypeId = Id<TypeDef>;
101
102#[derive(Clone, Debug, PartialEq, Eq)]
128pub struct UnresolvedPackage {
129 pub name: PackageName,
131
132 pub worlds: Arena<World>,
136
137 pub interfaces: Arena<Interface>,
144
145 pub types: Arena<TypeDef>,
152
153 pub foreign_deps: IndexMap<PackageName, IndexMap<String, (AstItem, Vec<Stability>)>>,
162
163 pub docs: Docs,
165
166 #[cfg_attr(not(feature = "std"), allow(dead_code))]
167 package_name_span: Span,
168 unknown_type_spans: Vec<Span>,
169 foreign_dep_spans: Vec<Span>,
170 required_resource_types: Vec<(TypeId, Span)>,
171}
172
173impl UnresolvedPackage {
174 pub(crate) fn adjust_spans(&mut self, offset: u32) {
179 self.package_name_span.adjust(offset);
181 for span in &mut self.unknown_type_spans {
182 span.adjust(offset);
183 }
184 for span in &mut self.foreign_dep_spans {
185 span.adjust(offset);
186 }
187 for (_, span) in &mut self.required_resource_types {
188 span.adjust(offset);
189 }
190
191 for (_, world) in self.worlds.iter_mut() {
193 world.adjust_spans(offset);
194 }
195 for (_, iface) in self.interfaces.iter_mut() {
196 iface.adjust_spans(offset);
197 }
198 for (_, ty) in self.types.iter_mut() {
199 ty.adjust_spans(offset);
200 }
201 }
202}
203
204#[derive(Clone, Debug, PartialEq, Eq)]
206pub struct UnresolvedPackageGroup {
207 pub main: UnresolvedPackage,
212
213 pub nested: Vec<UnresolvedPackage>,
215
216 pub source_map: SourceMap,
218}
219
220#[derive(Debug, Copy, Clone, PartialEq, Eq)]
221#[cfg_attr(feature = "serde", derive(Serialize))]
222#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
223pub enum AstItem {
224 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
225 Interface(InterfaceId),
226 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
227 World(WorldId),
228}
229
230#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
236#[cfg_attr(feature = "serde", derive(Serialize))]
237#[cfg_attr(feature = "serde", serde(into = "String"))]
238pub struct PackageName {
239 pub namespace: String,
241 pub name: String,
243 pub version: Option<Version>,
245}
246
247impl From<PackageName> for String {
248 fn from(name: PackageName) -> String {
249 name.to_string()
250 }
251}
252
253impl PackageName {
254 pub fn interface_id(&self, interface: &str) -> String {
257 let mut s = String::new();
258 s.push_str(&format!("{}:{}/{interface}", self.namespace, self.name));
259 if let Some(version) = &self.version {
260 s.push_str(&format!("@{version}"));
261 }
262 s
263 }
264
265 pub fn version_compat_track(version: &Version) -> Version {
278 let mut version = version.clone();
279 version.build = semver::BuildMetadata::EMPTY;
280 if !version.pre.is_empty() {
281 return version;
282 }
283 if version.major != 0 {
284 version.minor = 0;
285 version.patch = 0;
286 return version;
287 }
288 if version.minor != 0 {
289 version.patch = 0;
290 return version;
291 }
292 version
293 }
294
295 pub fn version_compat_track_string(version: &Version) -> String {
299 let version = Self::version_compat_track(version);
300 if !version.pre.is_empty() {
301 return version.to_string();
302 }
303 if version.major != 0 {
304 return format!("{}", version.major);
305 }
306 if version.minor != 0 {
307 return format!("{}.{}", version.major, version.minor);
308 }
309 version.to_string()
310 }
311}
312
313impl fmt::Display for PackageName {
314 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315 write!(f, "{}:{}", self.namespace, self.name)?;
316 if let Some(version) = &self.version {
317 write!(f, "@{version}")?;
318 }
319 Ok(())
320 }
321}
322
323impl UnresolvedPackageGroup {
324 #[cfg(feature = "std")]
334 pub fn parse(
335 path: impl AsRef<Path>,
336 contents: &str,
337 ) -> Result<UnresolvedPackageGroup, (SourceMap, ParseError)> {
338 let mut map = SourceMap::default();
339 map.push(path.as_ref(), contents);
340 map.parse()
341 }
342
343 #[cfg(feature = "std")]
350 pub fn parse_dir(path: impl AsRef<Path>) -> anyhow::Result<UnresolvedPackageGroup> {
351 let mut map = SourceMap::default();
352 map.push_dir(path.as_ref())?;
353 map.parse().map_err(|(map, e)| {
354 let rendered = e.render(&map);
355 anyhow::Error::from(e).context(rendered)
356 })
357 }
358}
359
360#[derive(Debug, Clone, PartialEq, Eq)]
361#[cfg_attr(feature = "serde", derive(Serialize))]
362pub struct World {
363 pub name: String,
365
366 pub imports: IndexMap<WorldKey, WorldItem>,
368
369 pub exports: IndexMap<WorldKey, WorldItem>,
371
372 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
374 pub package: Option<PackageId>,
375
376 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
378 pub docs: Docs,
379
380 #[cfg_attr(
382 feature = "serde",
383 serde(skip_serializing_if = "Stability::is_unknown")
384 )]
385 pub stability: Stability,
386
387 #[cfg_attr(feature = "serde", serde(skip))]
389 pub includes: Vec<WorldInclude>,
390
391 #[cfg_attr(feature = "serde", serde(skip))]
393 pub span: Span,
394}
395
396impl World {
397 pub(crate) fn adjust_spans(&mut self, offset: u32) {
399 self.span.adjust(offset);
400 for item in self.imports.values_mut().chain(self.exports.values_mut()) {
401 item.adjust_spans(offset);
402 }
403 for include in &mut self.includes {
404 include.span.adjust(offset);
405 }
406 }
407}
408
409#[derive(Debug, Clone, PartialEq, Eq)]
410pub struct IncludeName {
411 pub name: String,
413
414 pub as_: String,
416}
417
418#[derive(Debug, Clone, PartialEq, Eq)]
421pub struct WorldInclude {
422 pub stability: Stability,
424
425 pub id: WorldId,
427
428 pub names: Vec<IncludeName>,
430
431 pub span: Span,
433}
434
435#[derive(Debug, Clone, Eq)]
438#[cfg_attr(feature = "serde", derive(Serialize))]
439#[cfg_attr(feature = "serde", serde(into = "String"))]
440pub enum WorldKey {
441 Name(String),
443 Interface(InterfaceId),
445}
446
447impl Hash for WorldKey {
448 fn hash<H: Hasher>(&self, hasher: &mut H) {
449 match self {
450 WorldKey::Name(s) => {
451 0u8.hash(hasher);
452 s.as_str().hash(hasher);
453 }
454 WorldKey::Interface(i) => {
455 1u8.hash(hasher);
456 i.hash(hasher);
457 }
458 }
459 }
460}
461
462impl PartialEq for WorldKey {
463 fn eq(&self, other: &WorldKey) -> bool {
464 match (self, other) {
465 (WorldKey::Name(a), WorldKey::Name(b)) => a.as_str() == b.as_str(),
466 (WorldKey::Name(_), _) => false,
467 (WorldKey::Interface(a), WorldKey::Interface(b)) => a == b,
468 (WorldKey::Interface(_), _) => false,
469 }
470 }
471}
472
473impl From<WorldKey> for String {
474 fn from(key: WorldKey) -> String {
475 match key {
476 WorldKey::Name(name) => name,
477 WorldKey::Interface(id) => format!("interface-{}", id.index()),
478 }
479 }
480}
481
482impl WorldKey {
483 #[track_caller]
485 pub fn unwrap_name(self) -> String {
486 match self {
487 WorldKey::Name(name) => name,
488 WorldKey::Interface(_) => panic!("expected a name, found interface"),
489 }
490 }
491}
492
493#[derive(Debug, Clone, PartialEq, Eq)]
494#[cfg_attr(feature = "serde", derive(Serialize))]
495#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
496pub enum WorldItem {
497 Interface {
500 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
501 id: InterfaceId,
502 #[cfg_attr(
503 feature = "serde",
504 serde(skip_serializing_if = "Stability::is_unknown")
505 )]
506 stability: Stability,
507 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
508 external_id: Option<String>,
509 #[cfg_attr(
511 feature = "serde",
512 serde(default, skip_serializing_if = "Docs::is_empty")
513 )]
514 docs: Docs,
515 #[cfg_attr(feature = "serde", serde(skip))]
516 span: Span,
517 },
518
519 Function(Function),
521
522 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_ignore_span"))]
526 Type { id: TypeId, span: Span },
527}
528
529impl WorldItem {
530 pub fn stability<'a>(&'a self, resolve: &'a Resolve) -> &'a Stability {
531 match self {
532 WorldItem::Interface { stability, .. } => stability,
533 WorldItem::Function(f) => &f.stability,
534 WorldItem::Type { id, .. } => &resolve.types[*id].stability,
535 }
536 }
537
538 pub fn span(&self) -> Span {
539 match self {
540 WorldItem::Interface { span, .. } => *span,
541 WorldItem::Function(f) => f.span,
542 WorldItem::Type { span, .. } => *span,
543 }
544 }
545
546 pub(crate) fn adjust_spans(&mut self, offset: u32) {
547 match self {
548 WorldItem::Function(f) => f.adjust_spans(offset),
549 WorldItem::Interface { span, .. } => span.adjust(offset),
550 WorldItem::Type { span, .. } => span.adjust(offset),
551 }
552 }
553}
554
555#[derive(Debug, Clone, PartialEq, Eq)]
556#[cfg_attr(feature = "serde", derive(Serialize))]
557pub struct Interface {
558 pub name: Option<String>,
562
563 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
568 pub types: IndexMap<String, TypeId>,
569
570 pub functions: IndexMap<String, Function>,
572
573 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
575 pub docs: Docs,
576
577 #[cfg_attr(
579 feature = "serde",
580 serde(skip_serializing_if = "Stability::is_unknown")
581 )]
582 pub stability: Stability,
583
584 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
586 pub package: Option<PackageId>,
587
588 #[cfg_attr(feature = "serde", serde(skip))]
590 pub span: Span,
591
592 #[cfg_attr(
596 feature = "serde",
597 serde(
598 skip_serializing_if = "Option::is_none",
599 serialize_with = "serialize_optional_id",
600 )
601 )]
602 pub clone_of: Option<InterfaceId>,
603}
604
605impl Interface {
606 pub(crate) fn adjust_spans(&mut self, offset: u32) {
608 self.span.adjust(offset);
609 for func in self.functions.values_mut() {
610 func.adjust_spans(offset);
611 }
612 }
613}
614
615#[derive(Debug, Clone, PartialEq, Eq)]
616#[cfg_attr(feature = "serde", derive(Serialize))]
617pub struct TypeDef {
618 pub name: Option<String>,
619 pub kind: TypeDefKind,
620 pub owner: TypeOwner,
621 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
622 pub docs: Docs,
623 #[cfg_attr(
625 feature = "serde",
626 serde(skip_serializing_if = "Stability::is_unknown")
627 )]
628 pub stability: Stability,
629 #[cfg_attr(feature = "serde", serde(skip))]
631 pub span: Span,
632 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
633 pub external_id: Option<String>,
634}
635
636impl TypeDef {
637 pub(crate) fn adjust_spans(&mut self, offset: u32) {
642 self.span.adjust(offset);
643 match &mut self.kind {
644 TypeDefKind::Record(r) => {
645 for field in &mut r.fields {
646 field.span.adjust(offset);
647 }
648 }
649 TypeDefKind::Variant(v) => {
650 for case in &mut v.cases {
651 case.span.adjust(offset);
652 }
653 }
654 TypeDefKind::Enum(e) => {
655 for case in &mut e.cases {
656 case.span.adjust(offset);
657 }
658 }
659 TypeDefKind::Flags(f) => {
660 for flag in &mut f.flags {
661 flag.span.adjust(offset);
662 }
663 }
664 _ => {}
665 }
666 }
667}
668
669#[derive(Debug, Clone, PartialEq, Hash, Eq)]
670#[cfg_attr(feature = "serde", derive(Serialize))]
671#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
672pub enum TypeDefKind {
673 Record(Record),
674 Resource,
675 Handle(Handle),
676 Flags(Flags),
677 Tuple(Tuple),
678 Variant(Variant),
679 Enum(Enum),
680 Option(Type),
681 Result(Result_),
682 List(Type),
683 Map(Type, Type),
684 FixedLengthList(Type, u32),
685 Future(Option<Type>),
686 Stream(Option<Type>),
687 Type(Type),
688
689 Unknown,
695}
696
697impl TypeDefKind {
698 pub fn as_str(&self) -> &'static str {
699 match self {
700 TypeDefKind::Record(_) => "record",
701 TypeDefKind::Resource => "resource",
702 TypeDefKind::Handle(handle) => match handle {
703 Handle::Own(_) => "own",
704 Handle::Borrow(_) => "borrow",
705 },
706 TypeDefKind::Flags(_) => "flags",
707 TypeDefKind::Tuple(_) => "tuple",
708 TypeDefKind::Variant(_) => "variant",
709 TypeDefKind::Enum(_) => "enum",
710 TypeDefKind::Option(_) => "option",
711 TypeDefKind::Result(_) => "result",
712 TypeDefKind::List(_) => "list",
713 TypeDefKind::Map(_, _) => "map",
714 TypeDefKind::FixedLengthList(..) => "fixed-length list",
715 TypeDefKind::Future(_) => "future",
716 TypeDefKind::Stream(_) => "stream",
717 TypeDefKind::Type(_) => "type",
718 TypeDefKind::Unknown => "unknown",
719 }
720 }
721}
722
723#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
724#[cfg_attr(feature = "serde", derive(Serialize))]
725#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
726pub enum TypeOwner {
727 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
729 World(WorldId),
730 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
732 Interface(InterfaceId),
733 #[cfg_attr(feature = "serde", serde(untagged, serialize_with = "serialize_none"))]
736 None,
737}
738
739#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
740#[cfg_attr(feature = "serde", derive(Serialize))]
741#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
742pub enum Handle {
743 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
744 Own(TypeId),
745 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
746 Borrow(TypeId),
747}
748
749#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
750pub enum Type {
751 Bool,
752 U8,
753 U16,
754 U32,
755 U64,
756 S8,
757 S16,
758 S32,
759 S64,
760 F32,
761 F64,
762 Char,
763 String,
764 ErrorContext,
765 Id(TypeId),
766}
767
768#[derive(Debug, Copy, Clone, Eq, PartialEq)]
769pub enum Int {
770 U8,
771 U16,
772 U32,
773 U64,
774}
775
776#[derive(Debug, Clone, PartialEq, Hash, Eq)]
777#[cfg_attr(feature = "serde", derive(Serialize))]
778pub struct Record {
779 pub fields: Vec<Field>,
780}
781
782#[derive(Debug, Clone, PartialEq, Hash, Eq)]
783#[cfg_attr(feature = "serde", derive(Serialize))]
784pub struct Field {
785 pub name: String,
786 #[cfg_attr(feature = "serde", serde(rename = "type"))]
787 pub ty: Type,
788 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
789 pub docs: Docs,
790 #[cfg_attr(feature = "serde", serde(skip))]
792 pub span: Span,
793}
794
795#[derive(Debug, Clone, PartialEq, Hash, Eq)]
796#[cfg_attr(feature = "serde", derive(Serialize))]
797pub struct Flags {
798 pub flags: Vec<Flag>,
799}
800
801#[derive(Debug, Clone, PartialEq, Hash, Eq)]
802#[cfg_attr(feature = "serde", derive(Serialize))]
803pub struct Flag {
804 pub name: String,
805 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
806 pub docs: Docs,
807 #[cfg_attr(feature = "serde", serde(skip))]
809 pub span: Span,
810}
811
812#[derive(Debug, Clone, PartialEq)]
813pub enum FlagsRepr {
814 U8,
815 U16,
816 U32(usize),
817}
818
819impl Flags {
820 pub fn repr(&self) -> FlagsRepr {
821 match self.flags.len() {
822 0 => FlagsRepr::U32(0),
823 n if n <= 8 => FlagsRepr::U8,
824 n if n <= 16 => FlagsRepr::U16,
825 n => FlagsRepr::U32(sizealign::align_to(n, 32) / 32),
826 }
827 }
828}
829
830impl FlagsRepr {
831 pub fn count(&self) -> usize {
832 match self {
833 FlagsRepr::U8 => 1,
834 FlagsRepr::U16 => 1,
835 FlagsRepr::U32(n) => *n,
836 }
837 }
838}
839
840#[derive(Debug, Clone, PartialEq, Hash, Eq)]
841#[cfg_attr(feature = "serde", derive(Serialize))]
842pub struct Tuple {
843 pub types: Vec<Type>,
844}
845
846#[derive(Debug, Clone, PartialEq, Hash, Eq)]
847#[cfg_attr(feature = "serde", derive(Serialize))]
848pub struct Variant {
849 pub cases: Vec<Case>,
850}
851
852#[derive(Debug, Clone, PartialEq, Hash, Eq)]
853#[cfg_attr(feature = "serde", derive(Serialize))]
854pub struct Case {
855 pub name: String,
856 #[cfg_attr(feature = "serde", serde(rename = "type"))]
857 pub ty: Option<Type>,
858 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
859 pub docs: Docs,
860 #[cfg_attr(feature = "serde", serde(skip))]
862 pub span: Span,
863}
864
865impl Variant {
866 pub fn tag(&self) -> Int {
867 discriminant_type(self.cases.len())
868 }
869}
870
871#[derive(Debug, Clone, PartialEq, Hash, Eq)]
872#[cfg_attr(feature = "serde", derive(Serialize))]
873pub struct Enum {
874 pub cases: Vec<EnumCase>,
875}
876
877#[derive(Debug, Clone, PartialEq, Hash, Eq)]
878#[cfg_attr(feature = "serde", derive(Serialize))]
879pub struct EnumCase {
880 pub name: String,
881 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
882 pub docs: Docs,
883 #[cfg_attr(feature = "serde", serde(skip))]
885 pub span: Span,
886}
887
888impl Enum {
889 pub fn tag(&self) -> Int {
890 discriminant_type(self.cases.len())
891 }
892}
893
894fn discriminant_type(num_cases: usize) -> Int {
896 match num_cases.checked_sub(1) {
897 None => Int::U8,
898 Some(n) if n <= u8::max_value() as usize => Int::U8,
899 Some(n) if n <= u16::max_value() as usize => Int::U16,
900 Some(n) if n <= u32::max_value() as usize => Int::U32,
901 _ => panic!("too many cases to fit in a repr"),
902 }
903}
904
905#[derive(Debug, Clone, PartialEq, Hash, Eq)]
906#[cfg_attr(feature = "serde", derive(Serialize))]
907pub struct Result_ {
908 pub ok: Option<Type>,
909 pub err: Option<Type>,
910}
911
912#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
913#[cfg_attr(feature = "serde", derive(Serialize))]
914pub struct Docs {
915 pub contents: Option<String>,
916}
917
918impl Docs {
919 pub fn is_empty(&self) -> bool {
920 self.contents.is_none()
921 }
922}
923
924#[derive(Debug, Clone, PartialEq, Eq)]
925#[cfg_attr(feature = "serde", derive(Serialize))]
926pub struct Param {
927 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
928 pub name: String,
929 #[cfg_attr(feature = "serde", serde(rename = "type"))]
930 pub ty: Type,
931 #[cfg_attr(feature = "serde", serde(skip))]
932 pub span: Span,
933}
934
935#[derive(Debug, Clone, PartialEq, Eq)]
936#[cfg_attr(feature = "serde", derive(Serialize))]
937pub struct Function {
938 pub name: String,
939 pub kind: FunctionKind,
940 pub params: Vec<Param>,
941 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
942 pub result: Option<Type>,
943 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
944 pub docs: Docs,
945 #[cfg_attr(
947 feature = "serde",
948 serde(skip_serializing_if = "Stability::is_unknown")
949 )]
950 pub stability: Stability,
951
952 #[cfg_attr(feature = "serde", serde(skip))]
954 pub span: Span,
955 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
956 pub external_id: Option<String>,
957}
958
959#[derive(Debug, Clone, PartialEq, Eq)]
960#[cfg_attr(feature = "serde", derive(Serialize))]
961#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
962pub enum FunctionKind {
963 Freestanding,
971
972 AsyncFreestanding,
980
981 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
992 Method(TypeId),
993
994 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1005 AsyncMethod(TypeId),
1006
1007 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1017 Static(TypeId),
1018
1019 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1029 AsyncStatic(TypeId),
1030
1031 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1041 Constructor(TypeId),
1042}
1043
1044impl FunctionKind {
1045 pub fn is_async(&self) -> bool {
1047 match self {
1048 FunctionKind::Freestanding
1049 | FunctionKind::Method(_)
1050 | FunctionKind::Static(_)
1051 | FunctionKind::Constructor(_) => false,
1052 FunctionKind::AsyncFreestanding
1053 | FunctionKind::AsyncMethod(_)
1054 | FunctionKind::AsyncStatic(_) => true,
1055 }
1056 }
1057
1058 pub fn resource(&self) -> Option<TypeId> {
1060 match self {
1061 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
1062 FunctionKind::Method(id)
1063 | FunctionKind::Static(id)
1064 | FunctionKind::Constructor(id)
1065 | FunctionKind::AsyncMethod(id)
1066 | FunctionKind::AsyncStatic(id) => Some(*id),
1067 }
1068 }
1069
1070 pub fn resource_mut(&mut self) -> Option<&mut TypeId> {
1072 match self {
1073 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
1074 FunctionKind::Method(id)
1075 | FunctionKind::Static(id)
1076 | FunctionKind::Constructor(id)
1077 | FunctionKind::AsyncMethod(id)
1078 | FunctionKind::AsyncStatic(id) => Some(id),
1079 }
1080 }
1081}
1082
1083#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1085pub enum Mangling {
1086 Standard32,
1089
1090 Legacy,
1095}
1096
1097impl core::str::FromStr for Mangling {
1098 type Err = anyhow::Error;
1099
1100 fn from_str(s: &str) -> anyhow::Result<Mangling> {
1101 match s {
1102 "legacy" => Ok(Mangling::Legacy),
1103 "standard32" => Ok(Mangling::Standard32),
1104 _ => {
1105 anyhow::bail!(
1106 "unknown name mangling `{s}`, \
1107 supported values are `legacy` or `standard32`"
1108 )
1109 }
1110 }
1111 }
1112}
1113
1114#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1116pub enum LiftLowerAbi {
1117 Sync,
1119
1120 AsyncCallback,
1123
1124 AsyncStackful,
1127}
1128
1129impl LiftLowerAbi {
1130 fn import_prefix(self) -> &'static str {
1131 match self {
1132 Self::Sync => "",
1133 Self::AsyncCallback | Self::AsyncStackful => "[async-lower]",
1134 }
1135 }
1136
1137 pub fn import_variant(self) -> AbiVariant {
1139 match self {
1140 Self::Sync => AbiVariant::GuestImport,
1141 Self::AsyncCallback | Self::AsyncStackful => AbiVariant::GuestImportAsync,
1142 }
1143 }
1144
1145 fn export_prefix(self) -> &'static str {
1146 match self {
1147 Self::Sync => "",
1148 Self::AsyncCallback => "[async-lift]",
1149 Self::AsyncStackful => "[async-lift-stackful]",
1150 }
1151 }
1152
1153 pub fn export_variant(self) -> AbiVariant {
1155 match self {
1156 Self::Sync => AbiVariant::GuestExport,
1157 Self::AsyncCallback => AbiVariant::GuestExportAsync,
1158 Self::AsyncStackful => AbiVariant::GuestExportAsyncStackful,
1159 }
1160 }
1161}
1162
1163#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1165pub enum ManglingAndAbi {
1166 Standard32,
1171
1172 Legacy(LiftLowerAbi),
1174}
1175
1176impl ManglingAndAbi {
1177 pub fn import_variant(self) -> AbiVariant {
1179 match self {
1180 Self::Standard32 => AbiVariant::GuestImport,
1181 Self::Legacy(abi) => abi.import_variant(),
1182 }
1183 }
1184
1185 pub fn export_variant(self) -> AbiVariant {
1187 match self {
1188 Self::Standard32 => AbiVariant::GuestExport,
1189 Self::Legacy(abi) => abi.export_variant(),
1190 }
1191 }
1192
1193 pub fn sync(self) -> Self {
1195 match self {
1196 Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => self,
1197 Self::Legacy(LiftLowerAbi::AsyncCallback)
1198 | Self::Legacy(LiftLowerAbi::AsyncStackful) => Self::Legacy(LiftLowerAbi::Sync),
1199 }
1200 }
1201
1202 pub fn is_async(&self) -> bool {
1204 match self {
1205 Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => false,
1206 Self::Legacy(LiftLowerAbi::AsyncCallback)
1207 | Self::Legacy(LiftLowerAbi::AsyncStackful) => true,
1208 }
1209 }
1210
1211 pub fn mangling(&self) -> Mangling {
1212 match self {
1213 Self::Standard32 => Mangling::Standard32,
1214 Self::Legacy(_) => Mangling::Legacy,
1215 }
1216 }
1217
1218 pub fn for_func(&self, func: &Function) -> Self {
1224 match self {
1225 Self::Standard32 => *self,
1226 Self::Legacy(abi) => {
1227 if !func.kind.is_async() {
1228 Self::Legacy(LiftLowerAbi::Sync)
1229 } else {
1230 Self::Legacy(*abi)
1231 }
1232 }
1233 }
1234 }
1235}
1236
1237impl Function {
1238 pub(crate) fn adjust_spans(&mut self, offset: u32) {
1240 self.span.adjust(offset);
1241 for param in &mut self.params {
1242 param.span.adjust(offset);
1243 }
1244 }
1245
1246 pub fn item_name(&self) -> &str {
1247 match &self.kind {
1248 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => &self.name,
1249 FunctionKind::Method(_)
1250 | FunctionKind::Static(_)
1251 | FunctionKind::AsyncMethod(_)
1252 | FunctionKind::AsyncStatic(_) => &self.name[self.name.find('.').unwrap() + 1..],
1253 FunctionKind::Constructor(_) => "constructor",
1254 }
1255 }
1256
1257 pub fn parameter_and_result_types(&self) -> impl Iterator<Item = Type> + '_ {
1262 self.params.iter().map(|p| p.ty).chain(self.result)
1263 }
1264
1265 pub fn standard32_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1267 self.core_export_name(interface, Mangling::Standard32)
1268 }
1269
1270 pub fn legacy_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1271 self.core_export_name(interface, Mangling::Legacy)
1272 }
1273 pub fn core_export_name<'a>(
1275 &'a self,
1276 interface: Option<&str>,
1277 mangling: Mangling,
1278 ) -> Cow<'a, str> {
1279 match interface {
1280 Some(interface) => match mangling {
1281 Mangling::Standard32 => Cow::Owned(format!("cm32p2|{interface}|{}", self.name)),
1282 Mangling::Legacy => Cow::Owned(format!("{interface}#{}", self.name)),
1283 },
1284 None => match mangling {
1285 Mangling::Standard32 => Cow::Owned(format!("cm32p2||{}", self.name)),
1286 Mangling::Legacy => Cow::Borrowed(&self.name),
1287 },
1288 }
1289 }
1290 pub fn find_futures_and_streams(&self, resolve: &Resolve) -> Vec<TypeId> {
1306 let mut results = Vec::new();
1307 for param in self.params.iter() {
1308 find_futures_and_streams(resolve, param.ty, &mut results);
1309 }
1310 if let Some(ty) = self.result {
1311 find_futures_and_streams(resolve, ty, &mut results);
1312 }
1313 results
1314 }
1315
1316 pub fn is_constructor_shorthand(&self, resolve: &Resolve) -> bool {
1319 let FunctionKind::Constructor(containing_resource_id) = self.kind else {
1320 return false;
1321 };
1322
1323 let Some(Type::Id(id)) = &self.result else {
1324 return false;
1325 };
1326
1327 let TypeDefKind::Handle(Handle::Own(returned_resource_id)) = resolve.types[*id].kind else {
1328 return false;
1329 };
1330
1331 return containing_resource_id == returned_resource_id;
1332 }
1333
1334 pub fn task_return_import(
1337 &self,
1338 resolve: &Resolve,
1339 interface: Option<&WorldKey>,
1340 mangling: Mangling,
1341 ) -> (String, String, abi::WasmSignature) {
1342 match mangling {
1343 Mangling::Standard32 => todo!(),
1344 Mangling::Legacy => {}
1345 }
1346 let module = match interface {
1348 Some(key) => format!("[export]{}", resolve.name_world_key(key)),
1349 None => "[export]$root".to_string(),
1350 };
1351 let name = format!("[task-return]{}", self.name);
1352
1353 let mut func_tmp = self.clone();
1354 func_tmp.params = Vec::new();
1355 func_tmp.result = None;
1356 if let Some(ty) = self.result {
1357 func_tmp.params.push(Param {
1358 name: "x".to_string(),
1359 ty,
1360 span: Default::default(),
1361 });
1362 }
1363 let sig = resolve.wasm_signature(AbiVariant::GuestImport, &func_tmp);
1364 (module, name, sig)
1365 }
1366
1367 }
1369
1370fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeId>) {
1371 let Type::Id(id) = ty else {
1372 return;
1373 };
1374
1375 match &resolve.types[id].kind {
1376 TypeDefKind::Resource
1377 | TypeDefKind::Handle(_)
1378 | TypeDefKind::Flags(_)
1379 | TypeDefKind::Enum(_) => {}
1380 TypeDefKind::Record(r) => {
1381 for Field { ty, .. } in &r.fields {
1382 find_futures_and_streams(resolve, *ty, results);
1383 }
1384 }
1385 TypeDefKind::Tuple(t) => {
1386 for ty in &t.types {
1387 find_futures_and_streams(resolve, *ty, results);
1388 }
1389 }
1390 TypeDefKind::Variant(v) => {
1391 for Case { ty, .. } in &v.cases {
1392 if let Some(ty) = ty {
1393 find_futures_and_streams(resolve, *ty, results);
1394 }
1395 }
1396 }
1397 TypeDefKind::Option(ty)
1398 | TypeDefKind::List(ty)
1399 | TypeDefKind::FixedLengthList(ty, ..)
1400 | TypeDefKind::Type(ty) => {
1401 find_futures_and_streams(resolve, *ty, results);
1402 }
1403 TypeDefKind::Map(k, v) => {
1404 find_futures_and_streams(resolve, *k, results);
1405 find_futures_and_streams(resolve, *v, results);
1406 }
1407 TypeDefKind::Result(r) => {
1408 if let Some(ty) = r.ok {
1409 find_futures_and_streams(resolve, ty, results);
1410 }
1411 if let Some(ty) = r.err {
1412 find_futures_and_streams(resolve, ty, results);
1413 }
1414 }
1415 TypeDefKind::Future(ty) => {
1416 if let Some(ty) = ty {
1417 find_futures_and_streams(resolve, *ty, results);
1418 }
1419 results.push(id);
1420 }
1421 TypeDefKind::Stream(ty) => {
1422 if let Some(ty) = ty {
1423 find_futures_and_streams(resolve, *ty, results);
1424 }
1425 results.push(id);
1426 }
1427 TypeDefKind::Unknown => unreachable!(),
1428 }
1429}
1430
1431#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1439#[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
1440#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1441pub enum Stability {
1442 Unknown,
1444
1445 Unstable {
1450 feature: String,
1451 #[cfg_attr(
1452 feature = "serde",
1453 serde(
1454 skip_serializing_if = "Option::is_none",
1455 default,
1456 serialize_with = "serialize_optional_version",
1457 deserialize_with = "deserialize_optional_version"
1458 )
1459 )]
1460 deprecated: Option<Version>,
1461 },
1462
1463 Stable {
1468 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_version"))]
1469 #[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_version"))]
1470 since: Version,
1471 #[cfg_attr(
1472 feature = "serde",
1473 serde(
1474 skip_serializing_if = "Option::is_none",
1475 default,
1476 serialize_with = "serialize_optional_version",
1477 deserialize_with = "deserialize_optional_version"
1478 )
1479 )]
1480 deprecated: Option<Version>,
1481 },
1482}
1483
1484impl Stability {
1485 pub fn is_unknown(&self) -> bool {
1487 matches!(self, Stability::Unknown)
1488 }
1489
1490 pub fn is_stable(&self) -> bool {
1491 matches!(self, Stability::Stable { .. })
1492 }
1493}
1494
1495impl Default for Stability {
1496 fn default() -> Stability {
1497 Stability::Unknown
1498 }
1499}
1500
1501#[cfg(test)]
1502mod test {
1503 use super::*;
1504 use alloc::vec;
1505
1506 #[test]
1507 fn test_discriminant_type() {
1508 assert_eq!(discriminant_type(1), Int::U8);
1509 assert_eq!(discriminant_type(0x100), Int::U8);
1510 assert_eq!(discriminant_type(0x101), Int::U16);
1511 assert_eq!(discriminant_type(0x10000), Int::U16);
1512 assert_eq!(discriminant_type(0x10001), Int::U32);
1513 if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
1514 assert_eq!(discriminant_type(num_cases), Int::U32);
1515 }
1516 }
1517
1518 #[test]
1519 fn test_find_futures_and_streams() {
1520 let mut resolve = Resolve::default();
1521 let t0 = resolve.types.alloc(TypeDef {
1522 name: None,
1523 kind: TypeDefKind::Future(Some(Type::U32)),
1524 owner: TypeOwner::None,
1525 docs: Docs::default(),
1526 stability: Stability::Unknown,
1527 span: Default::default(),
1528 external_id: Default::default(),
1529 });
1530 let t1 = resolve.types.alloc(TypeDef {
1531 name: None,
1532 kind: TypeDefKind::Future(Some(Type::Id(t0))),
1533 owner: TypeOwner::None,
1534 docs: Docs::default(),
1535 stability: Stability::Unknown,
1536 span: Default::default(),
1537 external_id: Default::default(),
1538 });
1539 let t2 = resolve.types.alloc(TypeDef {
1540 name: None,
1541 kind: TypeDefKind::Stream(Some(Type::U32)),
1542 owner: TypeOwner::None,
1543 docs: Docs::default(),
1544 stability: Stability::Unknown,
1545 span: Default::default(),
1546 external_id: Default::default(),
1547 });
1548 let found = Function {
1549 name: "foo".into(),
1550 kind: FunctionKind::Freestanding,
1551 params: vec![
1552 Param {
1553 name: "p1".into(),
1554 ty: Type::Id(t1),
1555 span: Default::default(),
1556 },
1557 Param {
1558 name: "p2".into(),
1559 ty: Type::U32,
1560 span: Default::default(),
1561 },
1562 ],
1563 result: Some(Type::Id(t2)),
1564 docs: Docs::default(),
1565 stability: Stability::Unknown,
1566 span: Default::default(),
1567 external_id: Default::default(),
1568 }
1569 .find_futures_and_streams(&resolve);
1570 assert_eq!(3, found.len());
1571 assert_eq!(t0, found[0]);
1572 assert_eq!(t1, found[1]);
1573 assert_eq!(t2, found[2]);
1574 }
1575}