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;
12#[cfg(feature = "std")]
13use anyhow::Context as _;
14use id_arena::{Arena, Id};
15use semver::Version;
16
17#[cfg(feature = "std")]
18pub type IndexMap<K, V> = indexmap::IndexMap<K, V, std::hash::RandomState>;
19#[cfg(feature = "std")]
20pub type IndexSet<T> = indexmap::IndexSet<T, std::hash::RandomState>;
21#[cfg(not(feature = "std"))]
22pub type IndexMap<K, V> = indexmap::IndexMap<K, V, hashbrown::DefaultHashBuilder>;
23#[cfg(not(feature = "std"))]
24pub type IndexSet<T> = indexmap::IndexSet<T, hashbrown::DefaultHashBuilder>;
25
26#[cfg(feature = "std")]
27pub(crate) use std::collections::{HashMap, HashSet};
28
29#[cfg(not(feature = "std"))]
30pub(crate) use hashbrown::{HashMap, HashSet};
31
32use alloc::borrow::Cow;
33use core::fmt;
34use core::hash::{Hash, Hasher};
35#[cfg(feature = "std")]
36use std::path::Path;
37
38#[cfg(feature = "decoding")]
39pub mod decoding;
40#[cfg(feature = "decoding")]
41mod metadata;
42#[cfg(feature = "decoding")]
43pub use metadata::PackageMetadata;
44
45pub mod abi;
46mod ast;
47pub use ast::SourceMap;
48pub use ast::error::*;
49pub use ast::lex::Span;
50pub use ast::{ParsedUsePath, parse_use_path};
51mod sizealign;
52pub use sizealign::*;
53mod resolve;
54pub use resolve::error::*;
55pub use resolve::*;
56mod live;
57pub use live::{LiveTypes, TypeIdVisitor};
58
59#[cfg(feature = "serde")]
60use serde_derive::Serialize;
61#[cfg(feature = "serde")]
62mod serde_;
63#[cfg(feature = "serde")]
64use serde_::*;
65
66pub fn validate_id(s: &str) -> anyhow::Result<()> {
68 ast::validate_id(0, s)?;
69 Ok(())
70}
71
72#[cfg(feature = "std")]
84pub fn render_anyhow_error(err: &anyhow::Error, source_map: &SourceMap) -> String {
85 err.chain()
86 .map(|layer| {
87 if let Some(re) = layer.downcast_ref::<ResolveError>() {
88 re.highlight(source_map)
89 } else if let Some(pe) = layer.downcast_ref::<ParseError>() {
90 pe.highlight(source_map)
91 } else {
92 layer.to_string()
93 }
94 })
95 .collect::<Vec<_>>()
96 .join(": ")
97}
98
99pub type WorldId = Id<World>;
100pub type InterfaceId = Id<Interface>;
101pub type TypeId = Id<TypeDef>;
102
103#[derive(Clone, PartialEq, Eq)]
129pub struct UnresolvedPackage {
130 pub name: PackageName,
132
133 pub worlds: Arena<World>,
137
138 pub interfaces: Arena<Interface>,
145
146 pub types: Arena<TypeDef>,
153
154 pub foreign_deps: IndexMap<PackageName, IndexMap<String, (AstItem, Vec<Stability>)>>,
163
164 pub docs: Docs,
166
167 #[cfg_attr(not(feature = "std"), allow(dead_code))]
168 package_name_span: Span,
169 unknown_type_spans: Vec<Span>,
170 foreign_dep_spans: Vec<Span>,
171 required_resource_types: Vec<(TypeId, Span)>,
172}
173
174impl UnresolvedPackage {
175 pub(crate) fn adjust_spans(&mut self, offset: u32) {
180 self.package_name_span.adjust(offset);
182 for span in &mut self.unknown_type_spans {
183 span.adjust(offset);
184 }
185 for span in &mut self.foreign_dep_spans {
186 span.adjust(offset);
187 }
188 for (_, span) in &mut self.required_resource_types {
189 span.adjust(offset);
190 }
191
192 for (_, world) in self.worlds.iter_mut() {
194 world.adjust_spans(offset);
195 }
196 for (_, iface) in self.interfaces.iter_mut() {
197 iface.adjust_spans(offset);
198 }
199 for (_, ty) in self.types.iter_mut() {
200 ty.adjust_spans(offset);
201 }
202 }
203}
204
205#[derive(Clone, PartialEq, Eq)]
207pub struct UnresolvedPackageGroup {
208 pub main: UnresolvedPackage,
213
214 pub nested: Vec<UnresolvedPackage>,
216
217 pub source_map: SourceMap,
219}
220
221#[derive(Debug, Copy, Clone, PartialEq, Eq)]
222#[cfg_attr(feature = "serde", derive(Serialize))]
223#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
224pub enum AstItem {
225 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
226 Interface(InterfaceId),
227 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
228 World(WorldId),
229}
230
231#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
237#[cfg_attr(feature = "serde", derive(Serialize))]
238#[cfg_attr(feature = "serde", serde(into = "String"))]
239pub struct PackageName {
240 pub namespace: String,
242 pub name: String,
244 pub version: Option<Version>,
246}
247
248impl From<PackageName> for String {
249 fn from(name: PackageName) -> String {
250 name.to_string()
251 }
252}
253
254impl PackageName {
255 pub fn interface_id(&self, interface: &str) -> String {
258 let mut s = String::new();
259 s.push_str(&format!("{}:{}/{interface}", self.namespace, self.name));
260 if let Some(version) = &self.version {
261 s.push_str(&format!("@{version}"));
262 }
263 s
264 }
265
266 pub fn version_compat_track(version: &Version) -> Version {
279 let mut version = version.clone();
280 version.build = semver::BuildMetadata::EMPTY;
281 if !version.pre.is_empty() {
282 return version;
283 }
284 if version.major != 0 {
285 version.minor = 0;
286 version.patch = 0;
287 return version;
288 }
289 if version.minor != 0 {
290 version.patch = 0;
291 return version;
292 }
293 version
294 }
295
296 pub fn version_compat_track_string(version: &Version) -> String {
300 let version = Self::version_compat_track(version);
301 if !version.pre.is_empty() {
302 return version.to_string();
303 }
304 if version.major != 0 {
305 return format!("{}", version.major);
306 }
307 if version.minor != 0 {
308 return format!("{}.{}", version.major, version.minor);
309 }
310 version.to_string()
311 }
312}
313
314impl fmt::Display for PackageName {
315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
316 write!(f, "{}:{}", self.namespace, self.name)?;
317 if let Some(version) = &self.version {
318 write!(f, "@{version}")?;
319 }
320 Ok(())
321 }
322}
323
324impl UnresolvedPackageGroup {
325 #[cfg(feature = "std")]
331 pub fn parse(path: impl AsRef<Path>, contents: &str) -> anyhow::Result<UnresolvedPackageGroup> {
332 let path = path
333 .as_ref()
334 .to_str()
335 .ok_or_else(|| anyhow::anyhow!("path is not valid utf-8: {:?}", path.as_ref()))?;
336 let mut map = SourceMap::default();
337 map.push_str(path, contents);
338 map.parse()
339 .map_err(|(map, e)| anyhow::anyhow!("{}", e.highlight(&map)))
340 }
341
342 #[cfg(feature = "std")]
349 pub fn parse_dir(path: impl AsRef<Path>) -> anyhow::Result<UnresolvedPackageGroup> {
350 let path = path.as_ref();
351 let mut map = SourceMap::default();
352 let cx = || format!("failed to read directory {path:?}");
353 for entry in path.read_dir().with_context(&cx)? {
354 let entry = entry.with_context(&cx)?;
355 let path = entry.path();
356 let ty = entry.file_type().with_context(&cx)?;
357 if ty.is_dir() {
358 continue;
359 }
360 if ty.is_symlink() {
361 if path.is_dir() {
362 continue;
363 }
364 }
365 let filename = match path.file_name().and_then(|s| s.to_str()) {
366 Some(name) => name,
367 None => continue,
368 };
369 if !filename.ends_with(".wit") {
370 continue;
371 }
372 map.push_file(&path)?;
373 }
374 map.parse()
375 .map_err(|(map, e)| anyhow::anyhow!("{}", e.highlight(&map)))
376 }
377}
378
379#[derive(Debug, Clone, PartialEq, Eq)]
380#[cfg_attr(feature = "serde", derive(Serialize))]
381pub struct World {
382 pub name: String,
384
385 pub imports: IndexMap<WorldKey, WorldItem>,
387
388 pub exports: IndexMap<WorldKey, WorldItem>,
390
391 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
393 pub package: Option<PackageId>,
394
395 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
397 pub docs: Docs,
398
399 #[cfg_attr(
401 feature = "serde",
402 serde(skip_serializing_if = "Stability::is_unknown")
403 )]
404 pub stability: Stability,
405
406 #[cfg_attr(feature = "serde", serde(skip))]
408 pub includes: Vec<WorldInclude>,
409
410 #[cfg_attr(feature = "serde", serde(skip))]
412 pub span: Span,
413}
414
415impl World {
416 pub(crate) fn adjust_spans(&mut self, offset: u32) {
418 self.span.adjust(offset);
419 for item in self.imports.values_mut().chain(self.exports.values_mut()) {
420 item.adjust_spans(offset);
421 }
422 for include in &mut self.includes {
423 include.span.adjust(offset);
424 }
425 }
426}
427
428#[derive(Debug, Clone, PartialEq, Eq)]
429pub struct IncludeName {
430 pub name: String,
432
433 pub as_: String,
435}
436
437#[derive(Debug, Clone, PartialEq, Eq)]
440pub struct WorldInclude {
441 pub stability: Stability,
443
444 pub id: WorldId,
446
447 pub names: Vec<IncludeName>,
449
450 pub span: Span,
452}
453
454#[derive(Debug, Clone, Eq)]
457#[cfg_attr(feature = "serde", derive(Serialize))]
458#[cfg_attr(feature = "serde", serde(into = "String"))]
459pub enum WorldKey {
460 Name(String),
462 Interface(InterfaceId),
464}
465
466impl Hash for WorldKey {
467 fn hash<H: Hasher>(&self, hasher: &mut H) {
468 match self {
469 WorldKey::Name(s) => {
470 0u8.hash(hasher);
471 s.as_str().hash(hasher);
472 }
473 WorldKey::Interface(i) => {
474 1u8.hash(hasher);
475 i.hash(hasher);
476 }
477 }
478 }
479}
480
481impl PartialEq for WorldKey {
482 fn eq(&self, other: &WorldKey) -> bool {
483 match (self, other) {
484 (WorldKey::Name(a), WorldKey::Name(b)) => a.as_str() == b.as_str(),
485 (WorldKey::Name(_), _) => false,
486 (WorldKey::Interface(a), WorldKey::Interface(b)) => a == b,
487 (WorldKey::Interface(_), _) => false,
488 }
489 }
490}
491
492impl From<WorldKey> for String {
493 fn from(key: WorldKey) -> String {
494 match key {
495 WorldKey::Name(name) => name,
496 WorldKey::Interface(id) => format!("interface-{}", id.index()),
497 }
498 }
499}
500
501impl WorldKey {
502 #[track_caller]
504 pub fn unwrap_name(self) -> String {
505 match self {
506 WorldKey::Name(name) => name,
507 WorldKey::Interface(_) => panic!("expected a name, found interface"),
508 }
509 }
510}
511
512#[derive(Debug, Clone, PartialEq, Eq)]
513#[cfg_attr(feature = "serde", derive(Serialize))]
514#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
515pub enum WorldItem {
516 Interface {
519 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
520 id: InterfaceId,
521 #[cfg_attr(
522 feature = "serde",
523 serde(skip_serializing_if = "Stability::is_unknown")
524 )]
525 stability: Stability,
526 #[cfg_attr(feature = "serde", serde(skip))]
527 span: Span,
528 },
529
530 Function(Function),
532
533 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_ignore_span"))]
537 Type { id: TypeId, span: Span },
538}
539
540impl WorldItem {
541 pub fn stability<'a>(&'a self, resolve: &'a Resolve) -> &'a Stability {
542 match self {
543 WorldItem::Interface { stability, .. } => stability,
544 WorldItem::Function(f) => &f.stability,
545 WorldItem::Type { id, .. } => &resolve.types[*id].stability,
546 }
547 }
548
549 pub fn span(&self) -> Span {
550 match self {
551 WorldItem::Interface { span, .. } => *span,
552 WorldItem::Function(f) => f.span,
553 WorldItem::Type { span, .. } => *span,
554 }
555 }
556
557 pub(crate) fn adjust_spans(&mut self, offset: u32) {
558 match self {
559 WorldItem::Function(f) => f.adjust_spans(offset),
560 WorldItem::Interface { span, .. } => span.adjust(offset),
561 WorldItem::Type { span, .. } => span.adjust(offset),
562 }
563 }
564}
565
566#[derive(Debug, Clone, PartialEq, Eq)]
567#[cfg_attr(feature = "serde", derive(Serialize))]
568pub struct Interface {
569 pub name: Option<String>,
573
574 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
579 pub types: IndexMap<String, TypeId>,
580
581 pub functions: IndexMap<String, Function>,
583
584 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
586 pub docs: Docs,
587
588 #[cfg_attr(
590 feature = "serde",
591 serde(skip_serializing_if = "Stability::is_unknown")
592 )]
593 pub stability: Stability,
594
595 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
597 pub package: Option<PackageId>,
598
599 #[cfg_attr(feature = "serde", serde(skip))]
601 pub span: Span,
602
603 #[cfg_attr(
607 feature = "serde",
608 serde(
609 skip_serializing_if = "Option::is_none",
610 serialize_with = "serialize_optional_id",
611 )
612 )]
613 pub clone_of: Option<InterfaceId>,
614}
615
616impl Interface {
617 pub(crate) fn adjust_spans(&mut self, offset: u32) {
619 self.span.adjust(offset);
620 for func in self.functions.values_mut() {
621 func.adjust_spans(offset);
622 }
623 }
624}
625
626#[derive(Debug, Clone, PartialEq, Eq)]
627#[cfg_attr(feature = "serde", derive(Serialize))]
628pub struct TypeDef {
629 pub name: Option<String>,
630 pub kind: TypeDefKind,
631 pub owner: TypeOwner,
632 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
633 pub docs: Docs,
634 #[cfg_attr(
636 feature = "serde",
637 serde(skip_serializing_if = "Stability::is_unknown")
638 )]
639 pub stability: Stability,
640 #[cfg_attr(feature = "serde", serde(skip))]
642 pub span: Span,
643}
644
645impl TypeDef {
646 pub(crate) fn adjust_spans(&mut self, offset: u32) {
651 self.span.adjust(offset);
652 match &mut self.kind {
653 TypeDefKind::Record(r) => {
654 for field in &mut r.fields {
655 field.span.adjust(offset);
656 }
657 }
658 TypeDefKind::Variant(v) => {
659 for case in &mut v.cases {
660 case.span.adjust(offset);
661 }
662 }
663 TypeDefKind::Enum(e) => {
664 for case in &mut e.cases {
665 case.span.adjust(offset);
666 }
667 }
668 TypeDefKind::Flags(f) => {
669 for flag in &mut f.flags {
670 flag.span.adjust(offset);
671 }
672 }
673 _ => {}
674 }
675 }
676}
677
678#[derive(Debug, Clone, PartialEq, Hash, Eq)]
679#[cfg_attr(feature = "serde", derive(Serialize))]
680#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
681pub enum TypeDefKind {
682 Record(Record),
683 Resource,
684 Handle(Handle),
685 Flags(Flags),
686 Tuple(Tuple),
687 Variant(Variant),
688 Enum(Enum),
689 Option(Type),
690 Result(Result_),
691 List(Type),
692 Map(Type, Type),
693 FixedLengthList(Type, u32),
694 Future(Option<Type>),
695 Stream(Option<Type>),
696 Type(Type),
697
698 Unknown,
704}
705
706impl TypeDefKind {
707 pub fn as_str(&self) -> &'static str {
708 match self {
709 TypeDefKind::Record(_) => "record",
710 TypeDefKind::Resource => "resource",
711 TypeDefKind::Handle(handle) => match handle {
712 Handle::Own(_) => "own",
713 Handle::Borrow(_) => "borrow",
714 },
715 TypeDefKind::Flags(_) => "flags",
716 TypeDefKind::Tuple(_) => "tuple",
717 TypeDefKind::Variant(_) => "variant",
718 TypeDefKind::Enum(_) => "enum",
719 TypeDefKind::Option(_) => "option",
720 TypeDefKind::Result(_) => "result",
721 TypeDefKind::List(_) => "list",
722 TypeDefKind::Map(_, _) => "map",
723 TypeDefKind::FixedLengthList(..) => "fixed-length list",
724 TypeDefKind::Future(_) => "future",
725 TypeDefKind::Stream(_) => "stream",
726 TypeDefKind::Type(_) => "type",
727 TypeDefKind::Unknown => "unknown",
728 }
729 }
730}
731
732#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
733#[cfg_attr(feature = "serde", derive(Serialize))]
734#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
735pub enum TypeOwner {
736 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
738 World(WorldId),
739 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
741 Interface(InterfaceId),
742 #[cfg_attr(feature = "serde", serde(untagged, serialize_with = "serialize_none"))]
745 None,
746}
747
748#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
749#[cfg_attr(feature = "serde", derive(Serialize))]
750#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
751pub enum Handle {
752 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
753 Own(TypeId),
754 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
755 Borrow(TypeId),
756}
757
758#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
759pub enum Type {
760 Bool,
761 U8,
762 U16,
763 U32,
764 U64,
765 S8,
766 S16,
767 S32,
768 S64,
769 F32,
770 F64,
771 Char,
772 String,
773 ErrorContext,
774 Id(TypeId),
775}
776
777#[derive(Debug, Copy, Clone, Eq, PartialEq)]
778pub enum Int {
779 U8,
780 U16,
781 U32,
782 U64,
783}
784
785#[derive(Debug, Clone, PartialEq, Hash, Eq)]
786#[cfg_attr(feature = "serde", derive(Serialize))]
787pub struct Record {
788 pub fields: Vec<Field>,
789}
790
791#[derive(Debug, Clone, PartialEq, Hash, Eq)]
792#[cfg_attr(feature = "serde", derive(Serialize))]
793pub struct Field {
794 pub name: String,
795 #[cfg_attr(feature = "serde", serde(rename = "type"))]
796 pub ty: Type,
797 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
798 pub docs: Docs,
799 #[cfg_attr(feature = "serde", serde(skip))]
801 pub span: Span,
802}
803
804#[derive(Debug, Clone, PartialEq, Hash, Eq)]
805#[cfg_attr(feature = "serde", derive(Serialize))]
806pub struct Flags {
807 pub flags: Vec<Flag>,
808}
809
810#[derive(Debug, Clone, PartialEq, Hash, Eq)]
811#[cfg_attr(feature = "serde", derive(Serialize))]
812pub struct Flag {
813 pub name: String,
814 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
815 pub docs: Docs,
816 #[cfg_attr(feature = "serde", serde(skip))]
818 pub span: Span,
819}
820
821#[derive(Debug, Clone, PartialEq)]
822pub enum FlagsRepr {
823 U8,
824 U16,
825 U32(usize),
826}
827
828impl Flags {
829 pub fn repr(&self) -> FlagsRepr {
830 match self.flags.len() {
831 0 => FlagsRepr::U32(0),
832 n if n <= 8 => FlagsRepr::U8,
833 n if n <= 16 => FlagsRepr::U16,
834 n => FlagsRepr::U32(sizealign::align_to(n, 32) / 32),
835 }
836 }
837}
838
839impl FlagsRepr {
840 pub fn count(&self) -> usize {
841 match self {
842 FlagsRepr::U8 => 1,
843 FlagsRepr::U16 => 1,
844 FlagsRepr::U32(n) => *n,
845 }
846 }
847}
848
849#[derive(Debug, Clone, PartialEq, Hash, Eq)]
850#[cfg_attr(feature = "serde", derive(Serialize))]
851pub struct Tuple {
852 pub types: Vec<Type>,
853}
854
855#[derive(Debug, Clone, PartialEq, Hash, Eq)]
856#[cfg_attr(feature = "serde", derive(Serialize))]
857pub struct Variant {
858 pub cases: Vec<Case>,
859}
860
861#[derive(Debug, Clone, PartialEq, Hash, Eq)]
862#[cfg_attr(feature = "serde", derive(Serialize))]
863pub struct Case {
864 pub name: String,
865 #[cfg_attr(feature = "serde", serde(rename = "type"))]
866 pub ty: Option<Type>,
867 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
868 pub docs: Docs,
869 #[cfg_attr(feature = "serde", serde(skip))]
871 pub span: Span,
872}
873
874impl Variant {
875 pub fn tag(&self) -> Int {
876 discriminant_type(self.cases.len())
877 }
878}
879
880#[derive(Debug, Clone, PartialEq, Hash, Eq)]
881#[cfg_attr(feature = "serde", derive(Serialize))]
882pub struct Enum {
883 pub cases: Vec<EnumCase>,
884}
885
886#[derive(Debug, Clone, PartialEq, Hash, Eq)]
887#[cfg_attr(feature = "serde", derive(Serialize))]
888pub struct EnumCase {
889 pub name: String,
890 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
891 pub docs: Docs,
892 #[cfg_attr(feature = "serde", serde(skip))]
894 pub span: Span,
895}
896
897impl Enum {
898 pub fn tag(&self) -> Int {
899 discriminant_type(self.cases.len())
900 }
901}
902
903fn discriminant_type(num_cases: usize) -> Int {
905 match num_cases.checked_sub(1) {
906 None => Int::U8,
907 Some(n) if n <= u8::max_value() as usize => Int::U8,
908 Some(n) if n <= u16::max_value() as usize => Int::U16,
909 Some(n) if n <= u32::max_value() as usize => Int::U32,
910 _ => panic!("too many cases to fit in a repr"),
911 }
912}
913
914#[derive(Debug, Clone, PartialEq, Hash, Eq)]
915#[cfg_attr(feature = "serde", derive(Serialize))]
916pub struct Result_ {
917 pub ok: Option<Type>,
918 pub err: Option<Type>,
919}
920
921#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
922#[cfg_attr(feature = "serde", derive(Serialize))]
923pub struct Docs {
924 pub contents: Option<String>,
925}
926
927impl Docs {
928 pub fn is_empty(&self) -> bool {
929 self.contents.is_none()
930 }
931}
932
933#[derive(Debug, Clone, PartialEq, Eq)]
934#[cfg_attr(feature = "serde", derive(Serialize))]
935pub struct Param {
936 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
937 pub name: String,
938 #[cfg_attr(feature = "serde", serde(rename = "type"))]
939 pub ty: Type,
940 #[cfg_attr(feature = "serde", serde(skip))]
941 pub span: Span,
942}
943
944#[derive(Debug, Clone, PartialEq, Eq)]
945#[cfg_attr(feature = "serde", derive(Serialize))]
946pub struct Function {
947 pub name: String,
948 pub kind: FunctionKind,
949 pub params: Vec<Param>,
950 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
951 pub result: Option<Type>,
952 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
953 pub docs: Docs,
954 #[cfg_attr(
956 feature = "serde",
957 serde(skip_serializing_if = "Stability::is_unknown")
958 )]
959 pub stability: Stability,
960
961 #[cfg_attr(feature = "serde", serde(skip))]
963 pub span: Span,
964}
965
966#[derive(Debug, Clone, PartialEq, Eq)]
967#[cfg_attr(feature = "serde", derive(Serialize))]
968#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
969pub enum FunctionKind {
970 Freestanding,
978
979 AsyncFreestanding,
987
988 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
999 Method(TypeId),
1000
1001 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1012 AsyncMethod(TypeId),
1013
1014 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1024 Static(TypeId),
1025
1026 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1036 AsyncStatic(TypeId),
1037
1038 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1048 Constructor(TypeId),
1049}
1050
1051impl FunctionKind {
1052 pub fn is_async(&self) -> bool {
1054 match self {
1055 FunctionKind::Freestanding
1056 | FunctionKind::Method(_)
1057 | FunctionKind::Static(_)
1058 | FunctionKind::Constructor(_) => false,
1059 FunctionKind::AsyncFreestanding
1060 | FunctionKind::AsyncMethod(_)
1061 | FunctionKind::AsyncStatic(_) => true,
1062 }
1063 }
1064
1065 pub fn resource(&self) -> Option<TypeId> {
1067 match self {
1068 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
1069 FunctionKind::Method(id)
1070 | FunctionKind::Static(id)
1071 | FunctionKind::Constructor(id)
1072 | FunctionKind::AsyncMethod(id)
1073 | FunctionKind::AsyncStatic(id) => Some(*id),
1074 }
1075 }
1076
1077 pub fn resource_mut(&mut self) -> Option<&mut TypeId> {
1079 match self {
1080 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
1081 FunctionKind::Method(id)
1082 | FunctionKind::Static(id)
1083 | FunctionKind::Constructor(id)
1084 | FunctionKind::AsyncMethod(id)
1085 | FunctionKind::AsyncStatic(id) => Some(id),
1086 }
1087 }
1088}
1089
1090#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1092pub enum Mangling {
1093 Standard32,
1096
1097 Legacy,
1102}
1103
1104impl core::str::FromStr for Mangling {
1105 type Err = anyhow::Error;
1106
1107 fn from_str(s: &str) -> anyhow::Result<Mangling> {
1108 match s {
1109 "legacy" => Ok(Mangling::Legacy),
1110 "standard32" => Ok(Mangling::Standard32),
1111 _ => {
1112 anyhow::bail!(
1113 "unknown name mangling `{s}`, \
1114 supported values are `legacy` or `standard32`"
1115 )
1116 }
1117 }
1118 }
1119}
1120
1121#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1123pub enum LiftLowerAbi {
1124 Sync,
1126
1127 AsyncCallback,
1130
1131 AsyncStackful,
1134}
1135
1136impl LiftLowerAbi {
1137 fn import_prefix(self) -> &'static str {
1138 match self {
1139 Self::Sync => "",
1140 Self::AsyncCallback | Self::AsyncStackful => "[async-lower]",
1141 }
1142 }
1143
1144 pub fn import_variant(self) -> AbiVariant {
1146 match self {
1147 Self::Sync => AbiVariant::GuestImport,
1148 Self::AsyncCallback | Self::AsyncStackful => AbiVariant::GuestImportAsync,
1149 }
1150 }
1151
1152 fn export_prefix(self) -> &'static str {
1153 match self {
1154 Self::Sync => "",
1155 Self::AsyncCallback => "[async-lift]",
1156 Self::AsyncStackful => "[async-lift-stackful]",
1157 }
1158 }
1159
1160 pub fn export_variant(self) -> AbiVariant {
1162 match self {
1163 Self::Sync => AbiVariant::GuestExport,
1164 Self::AsyncCallback => AbiVariant::GuestExportAsync,
1165 Self::AsyncStackful => AbiVariant::GuestExportAsyncStackful,
1166 }
1167 }
1168}
1169
1170#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1172pub enum ManglingAndAbi {
1173 Standard32,
1178
1179 Legacy(LiftLowerAbi),
1181}
1182
1183impl ManglingAndAbi {
1184 pub fn import_variant(self) -> AbiVariant {
1186 match self {
1187 Self::Standard32 => AbiVariant::GuestImport,
1188 Self::Legacy(abi) => abi.import_variant(),
1189 }
1190 }
1191
1192 pub fn export_variant(self) -> AbiVariant {
1194 match self {
1195 Self::Standard32 => AbiVariant::GuestExport,
1196 Self::Legacy(abi) => abi.export_variant(),
1197 }
1198 }
1199
1200 pub fn sync(self) -> Self {
1202 match self {
1203 Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => self,
1204 Self::Legacy(LiftLowerAbi::AsyncCallback)
1205 | Self::Legacy(LiftLowerAbi::AsyncStackful) => Self::Legacy(LiftLowerAbi::Sync),
1206 }
1207 }
1208
1209 pub fn is_async(&self) -> bool {
1211 match self {
1212 Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => false,
1213 Self::Legacy(LiftLowerAbi::AsyncCallback)
1214 | Self::Legacy(LiftLowerAbi::AsyncStackful) => true,
1215 }
1216 }
1217
1218 pub fn mangling(&self) -> Mangling {
1219 match self {
1220 Self::Standard32 => Mangling::Standard32,
1221 Self::Legacy(_) => Mangling::Legacy,
1222 }
1223 }
1224
1225 pub fn for_func(&self, func: &Function) -> Self {
1231 match self {
1232 Self::Standard32 => *self,
1233 Self::Legacy(abi) => {
1234 if !func.kind.is_async() {
1235 Self::Legacy(LiftLowerAbi::Sync)
1236 } else {
1237 Self::Legacy(*abi)
1238 }
1239 }
1240 }
1241 }
1242}
1243
1244impl Function {
1245 pub(crate) fn adjust_spans(&mut self, offset: u32) {
1247 self.span.adjust(offset);
1248 for param in &mut self.params {
1249 param.span.adjust(offset);
1250 }
1251 }
1252
1253 pub fn item_name(&self) -> &str {
1254 match &self.kind {
1255 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => &self.name,
1256 FunctionKind::Method(_)
1257 | FunctionKind::Static(_)
1258 | FunctionKind::AsyncMethod(_)
1259 | FunctionKind::AsyncStatic(_) => &self.name[self.name.find('.').unwrap() + 1..],
1260 FunctionKind::Constructor(_) => "constructor",
1261 }
1262 }
1263
1264 pub fn parameter_and_result_types(&self) -> impl Iterator<Item = Type> + '_ {
1269 self.params.iter().map(|p| p.ty).chain(self.result)
1270 }
1271
1272 pub fn standard32_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1274 self.core_export_name(interface, Mangling::Standard32)
1275 }
1276
1277 pub fn legacy_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1278 self.core_export_name(interface, Mangling::Legacy)
1279 }
1280 pub fn core_export_name<'a>(
1282 &'a self,
1283 interface: Option<&str>,
1284 mangling: Mangling,
1285 ) -> Cow<'a, str> {
1286 match interface {
1287 Some(interface) => match mangling {
1288 Mangling::Standard32 => Cow::Owned(format!("cm32p2|{interface}|{}", self.name)),
1289 Mangling::Legacy => Cow::Owned(format!("{interface}#{}", self.name)),
1290 },
1291 None => match mangling {
1292 Mangling::Standard32 => Cow::Owned(format!("cm32p2||{}", self.name)),
1293 Mangling::Legacy => Cow::Borrowed(&self.name),
1294 },
1295 }
1296 }
1297 pub fn find_futures_and_streams(&self, resolve: &Resolve) -> Vec<TypeId> {
1313 let mut results = Vec::new();
1314 for param in self.params.iter() {
1315 find_futures_and_streams(resolve, param.ty, &mut results);
1316 }
1317 if let Some(ty) = self.result {
1318 find_futures_and_streams(resolve, ty, &mut results);
1319 }
1320 results
1321 }
1322
1323 pub fn is_constructor_shorthand(&self, resolve: &Resolve) -> bool {
1326 let FunctionKind::Constructor(containing_resource_id) = self.kind else {
1327 return false;
1328 };
1329
1330 let Some(Type::Id(id)) = &self.result else {
1331 return false;
1332 };
1333
1334 let TypeDefKind::Handle(Handle::Own(returned_resource_id)) = resolve.types[*id].kind else {
1335 return false;
1336 };
1337
1338 return containing_resource_id == returned_resource_id;
1339 }
1340
1341 pub fn task_return_import(
1344 &self,
1345 resolve: &Resolve,
1346 interface: Option<&WorldKey>,
1347 mangling: Mangling,
1348 ) -> (String, String, abi::WasmSignature) {
1349 match mangling {
1350 Mangling::Standard32 => todo!(),
1351 Mangling::Legacy => {}
1352 }
1353 let module = match interface {
1355 Some(key) => format!("[export]{}", resolve.name_world_key(key)),
1356 None => "[export]$root".to_string(),
1357 };
1358 let name = format!("[task-return]{}", self.name);
1359
1360 let mut func_tmp = self.clone();
1361 func_tmp.params = Vec::new();
1362 func_tmp.result = None;
1363 if let Some(ty) = self.result {
1364 func_tmp.params.push(Param {
1365 name: "x".to_string(),
1366 ty,
1367 span: Default::default(),
1368 });
1369 }
1370 let sig = resolve.wasm_signature(AbiVariant::GuestImport, &func_tmp);
1371 (module, name, sig)
1372 }
1373
1374 }
1376
1377fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeId>) {
1378 let Type::Id(id) = ty else {
1379 return;
1380 };
1381
1382 match &resolve.types[id].kind {
1383 TypeDefKind::Resource
1384 | TypeDefKind::Handle(_)
1385 | TypeDefKind::Flags(_)
1386 | TypeDefKind::Enum(_) => {}
1387 TypeDefKind::Record(r) => {
1388 for Field { ty, .. } in &r.fields {
1389 find_futures_and_streams(resolve, *ty, results);
1390 }
1391 }
1392 TypeDefKind::Tuple(t) => {
1393 for ty in &t.types {
1394 find_futures_and_streams(resolve, *ty, results);
1395 }
1396 }
1397 TypeDefKind::Variant(v) => {
1398 for Case { ty, .. } in &v.cases {
1399 if let Some(ty) = ty {
1400 find_futures_and_streams(resolve, *ty, results);
1401 }
1402 }
1403 }
1404 TypeDefKind::Option(ty)
1405 | TypeDefKind::List(ty)
1406 | TypeDefKind::FixedLengthList(ty, ..)
1407 | TypeDefKind::Type(ty) => {
1408 find_futures_and_streams(resolve, *ty, results);
1409 }
1410 TypeDefKind::Map(k, v) => {
1411 find_futures_and_streams(resolve, *k, results);
1412 find_futures_and_streams(resolve, *v, results);
1413 }
1414 TypeDefKind::Result(r) => {
1415 if let Some(ty) = r.ok {
1416 find_futures_and_streams(resolve, ty, results);
1417 }
1418 if let Some(ty) = r.err {
1419 find_futures_and_streams(resolve, ty, results);
1420 }
1421 }
1422 TypeDefKind::Future(ty) => {
1423 if let Some(ty) = ty {
1424 find_futures_and_streams(resolve, *ty, results);
1425 }
1426 results.push(id);
1427 }
1428 TypeDefKind::Stream(ty) => {
1429 if let Some(ty) = ty {
1430 find_futures_and_streams(resolve, *ty, results);
1431 }
1432 results.push(id);
1433 }
1434 TypeDefKind::Unknown => unreachable!(),
1435 }
1436}
1437
1438#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1446#[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
1447#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1448pub enum Stability {
1449 Unknown,
1451
1452 Unstable {
1457 feature: String,
1458 #[cfg_attr(
1459 feature = "serde",
1460 serde(
1461 skip_serializing_if = "Option::is_none",
1462 default,
1463 serialize_with = "serialize_optional_version",
1464 deserialize_with = "deserialize_optional_version"
1465 )
1466 )]
1467 deprecated: Option<Version>,
1468 },
1469
1470 Stable {
1475 #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_version"))]
1476 #[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_version"))]
1477 since: Version,
1478 #[cfg_attr(
1479 feature = "serde",
1480 serde(
1481 skip_serializing_if = "Option::is_none",
1482 default,
1483 serialize_with = "serialize_optional_version",
1484 deserialize_with = "deserialize_optional_version"
1485 )
1486 )]
1487 deprecated: Option<Version>,
1488 },
1489}
1490
1491impl Stability {
1492 pub fn is_unknown(&self) -> bool {
1494 matches!(self, Stability::Unknown)
1495 }
1496
1497 pub fn is_stable(&self) -> bool {
1498 matches!(self, Stability::Stable { .. })
1499 }
1500}
1501
1502impl Default for Stability {
1503 fn default() -> Stability {
1504 Stability::Unknown
1505 }
1506}
1507
1508#[cfg(test)]
1509mod test {
1510 use super::*;
1511 use alloc::vec;
1512
1513 #[test]
1514 fn test_discriminant_type() {
1515 assert_eq!(discriminant_type(1), Int::U8);
1516 assert_eq!(discriminant_type(0x100), Int::U8);
1517 assert_eq!(discriminant_type(0x101), Int::U16);
1518 assert_eq!(discriminant_type(0x10000), Int::U16);
1519 assert_eq!(discriminant_type(0x10001), Int::U32);
1520 if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
1521 assert_eq!(discriminant_type(num_cases), Int::U32);
1522 }
1523 }
1524
1525 #[test]
1526 fn test_find_futures_and_streams() {
1527 let mut resolve = Resolve::default();
1528 let t0 = resolve.types.alloc(TypeDef {
1529 name: None,
1530 kind: TypeDefKind::Future(Some(Type::U32)),
1531 owner: TypeOwner::None,
1532 docs: Docs::default(),
1533 stability: Stability::Unknown,
1534 span: Default::default(),
1535 });
1536 let t1 = resolve.types.alloc(TypeDef {
1537 name: None,
1538 kind: TypeDefKind::Future(Some(Type::Id(t0))),
1539 owner: TypeOwner::None,
1540 docs: Docs::default(),
1541 stability: Stability::Unknown,
1542 span: Default::default(),
1543 });
1544 let t2 = resolve.types.alloc(TypeDef {
1545 name: None,
1546 kind: TypeDefKind::Stream(Some(Type::U32)),
1547 owner: TypeOwner::None,
1548 docs: Docs::default(),
1549 stability: Stability::Unknown,
1550 span: Default::default(),
1551 });
1552 let found = Function {
1553 name: "foo".into(),
1554 kind: FunctionKind::Freestanding,
1555 params: vec![
1556 Param {
1557 name: "p1".into(),
1558 ty: Type::Id(t1),
1559 span: Default::default(),
1560 },
1561 Param {
1562 name: "p2".into(),
1563 ty: Type::U32,
1564 span: Default::default(),
1565 },
1566 ],
1567 result: Some(Type::Id(t2)),
1568 docs: Docs::default(),
1569 stability: Stability::Unknown,
1570 span: Default::default(),
1571 }
1572 .find_futures_and_streams(&resolve);
1573 assert_eq!(3, found.len());
1574 assert_eq!(t0, found[0]);
1575 assert_eq!(t1, found[1]);
1576 assert_eq!(t2, found[2]);
1577 }
1578}