1use crate::abi::AbiVariant;
2use anyhow::{bail, Context, Result};
3use id_arena::{Arena, Id};
4use indexmap::IndexMap;
5use semver::Version;
6use std::borrow::Cow;
7use std::fmt;
8use std::path::Path;
9
10#[cfg(feature = "decoding")]
11pub mod decoding;
12#[cfg(feature = "decoding")]
13mod metadata;
14#[cfg(feature = "decoding")]
15pub use metadata::PackageMetadata;
16
17pub mod abi;
18mod ast;
19use ast::lex::Span;
20pub use ast::SourceMap;
21pub use ast::{parse_use_path, ParsedUsePath};
22mod sizealign;
23pub use sizealign::*;
24mod resolve;
25pub use resolve::*;
26mod live;
27pub use live::{LiveTypes, TypeIdVisitor};
28
29#[cfg(feature = "serde")]
30use serde_derive::Serialize;
31#[cfg(feature = "serde")]
32mod serde_;
33#[cfg(feature = "serde")]
34use serde_::*;
35
36pub fn validate_id(s: &str) -> Result<()> {
38    ast::validate_id(0, s)?;
39    Ok(())
40}
41
42pub type WorldId = Id<World>;
43pub type InterfaceId = Id<Interface>;
44pub type TypeId = Id<TypeDef>;
45
46#[derive(Clone)]
72pub struct UnresolvedPackage {
73    pub name: PackageName,
75
76    pub worlds: Arena<World>,
80
81    pub interfaces: Arena<Interface>,
88
89    pub types: Arena<TypeDef>,
96
97    pub foreign_deps: IndexMap<PackageName, IndexMap<String, AstItem>>,
106
107    pub docs: Docs,
109
110    package_name_span: Span,
111    unknown_type_spans: Vec<Span>,
112    interface_spans: Vec<InterfaceSpan>,
113    world_spans: Vec<WorldSpan>,
114    type_spans: Vec<Span>,
115    foreign_dep_spans: Vec<Span>,
116    required_resource_types: Vec<(TypeId, Span)>,
117}
118
119#[derive(Clone)]
121pub struct UnresolvedPackageGroup {
122    pub main: UnresolvedPackage,
127
128    pub nested: Vec<UnresolvedPackage>,
130
131    pub source_map: SourceMap,
133}
134
135#[derive(Clone)]
136struct WorldSpan {
137    span: Span,
138    imports: Vec<Span>,
139    exports: Vec<Span>,
140    includes: Vec<Span>,
141}
142
143#[derive(Clone)]
144struct InterfaceSpan {
145    span: Span,
146    funcs: Vec<Span>,
147}
148
149#[derive(Debug, Copy, Clone)]
150#[cfg_attr(feature = "serde", derive(Serialize))]
151#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
152pub enum AstItem {
153    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
154    Interface(InterfaceId),
155    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
156    World(WorldId),
157}
158
159#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
165#[cfg_attr(feature = "serde", derive(Serialize))]
166#[cfg_attr(feature = "serde", serde(into = "String"))]
167pub struct PackageName {
168    pub namespace: String,
170    pub name: String,
172    pub version: Option<Version>,
174}
175
176impl From<PackageName> for String {
177    fn from(name: PackageName) -> String {
178        name.to_string()
179    }
180}
181
182impl PackageName {
183    pub fn interface_id(&self, interface: &str) -> String {
186        let mut s = String::new();
187        s.push_str(&format!("{}:{}/{interface}", self.namespace, self.name));
188        if let Some(version) = &self.version {
189            s.push_str(&format!("@{version}"));
190        }
191        s
192    }
193
194    pub fn version_compat_track(version: &Version) -> Version {
207        let mut version = version.clone();
208        version.build = semver::BuildMetadata::EMPTY;
209        if !version.pre.is_empty() {
210            return version;
211        }
212        if version.major != 0 {
213            version.minor = 0;
214            version.patch = 0;
215            return version;
216        }
217        if version.minor != 0 {
218            version.patch = 0;
219            return version;
220        }
221        version
222    }
223
224    pub fn version_compat_track_string(version: &Version) -> String {
228        let version = Self::version_compat_track(version);
229        if !version.pre.is_empty() {
230            return version.to_string();
231        }
232        if version.major != 0 {
233            return format!("{}", version.major);
234        }
235        if version.minor != 0 {
236            return format!("{}.{}", version.major, version.minor);
237        }
238        version.to_string()
239    }
240}
241
242impl fmt::Display for PackageName {
243    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244        write!(f, "{}:{}", self.namespace, self.name)?;
245        if let Some(version) = &self.version {
246            write!(f, "@{version}")?;
247        }
248        Ok(())
249    }
250}
251
252#[derive(Debug)]
253struct Error {
254    span: Span,
255    msg: String,
256    highlighted: Option<String>,
257}
258
259impl Error {
260    fn new(span: Span, msg: impl Into<String>) -> Error {
261        Error {
262            span,
263            msg: msg.into(),
264            highlighted: None,
265        }
266    }
267}
268
269impl fmt::Display for Error {
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        self.highlighted.as_ref().unwrap_or(&self.msg).fmt(f)
272    }
273}
274
275impl std::error::Error for Error {}
276
277#[derive(Debug)]
278struct PackageNotFoundError {
279    span: Span,
280    requested: PackageName,
281    known: Vec<PackageName>,
282    highlighted: Option<String>,
283}
284
285impl PackageNotFoundError {
286    pub fn new(span: Span, requested: PackageName, known: Vec<PackageName>) -> Self {
287        Self {
288            span,
289            requested,
290            known,
291            highlighted: None,
292        }
293    }
294}
295
296impl fmt::Display for PackageNotFoundError {
297    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298        if let Some(highlighted) = &self.highlighted {
299            return highlighted.fmt(f);
300        }
301        if self.known.is_empty() {
302            write!(
303                f,
304                "package '{}' not found. no known packages.",
305                self.requested
306            )?;
307        } else {
308            write!(
309                f,
310                "package '{}' not found. known packages:\n",
311                self.requested
312            )?;
313            for known in self.known.iter() {
314                write!(f, "    {known}\n")?;
315            }
316        }
317        Ok(())
318    }
319}
320
321impl std::error::Error for PackageNotFoundError {}
322
323impl UnresolvedPackageGroup {
324    pub fn parse(path: impl AsRef<Path>, contents: &str) -> Result<UnresolvedPackageGroup> {
330        let mut map = SourceMap::default();
331        map.push(path.as_ref(), contents);
332        map.parse()
333    }
334
335    pub fn parse_path(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
341        let path = path.as_ref();
342        if path.is_dir() {
343            UnresolvedPackageGroup::parse_dir(path)
344        } else {
345            UnresolvedPackageGroup::parse_file(path)
346        }
347    }
348
349    pub fn parse_file(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
354        let path = path.as_ref();
355        let contents = std::fs::read_to_string(path)
356            .with_context(|| format!("failed to read file {path:?}"))?;
357        Self::parse(path, &contents)
358    }
359
360    pub fn parse_dir(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
367        let path = path.as_ref();
368        let mut map = SourceMap::default();
369        let cx = || format!("failed to read directory {path:?}");
370        for entry in path.read_dir().with_context(&cx)? {
371            let entry = entry.with_context(&cx)?;
372            let path = entry.path();
373            let ty = entry.file_type().with_context(&cx)?;
374            if ty.is_dir() {
375                continue;
376            }
377            if ty.is_symlink() {
378                if path.is_dir() {
379                    continue;
380                }
381            }
382            let filename = match path.file_name().and_then(|s| s.to_str()) {
383                Some(name) => name,
384                None => continue,
385            };
386            if !filename.ends_with(".wit") {
387                continue;
388            }
389            map.push_file(&path)?;
390        }
391        map.parse()
392    }
393}
394
395#[derive(Debug, Clone)]
396#[cfg_attr(feature = "serde", derive(Serialize))]
397pub struct World {
398    pub name: String,
400
401    pub imports: IndexMap<WorldKey, WorldItem>,
403
404    pub exports: IndexMap<WorldKey, WorldItem>,
406
407    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
409    pub package: Option<PackageId>,
410
411    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
413    pub docs: Docs,
414
415    #[cfg_attr(
417        feature = "serde",
418        serde(skip_serializing_if = "Stability::is_unknown")
419    )]
420    pub stability: Stability,
421
422    #[cfg_attr(feature = "serde", serde(skip))]
424    pub includes: Vec<(Stability, WorldId)>,
425
426    #[cfg_attr(feature = "serde", serde(skip))]
428    pub include_names: Vec<Vec<IncludeName>>,
429}
430
431#[derive(Debug, Clone)]
432pub struct IncludeName {
433    pub name: String,
435
436    pub as_: String,
438}
439
440#[derive(Debug, Clone, PartialEq, Eq, Hash)]
443#[cfg_attr(feature = "serde", derive(Serialize))]
444#[cfg_attr(feature = "serde", serde(into = "String"))]
445pub enum WorldKey {
446    Name(String),
448    Interface(InterfaceId),
450}
451
452impl From<WorldKey> for String {
453    fn from(key: WorldKey) -> String {
454        match key {
455            WorldKey::Name(name) => name,
456            WorldKey::Interface(id) => format!("interface-{}", id.index()),
457        }
458    }
459}
460
461impl WorldKey {
462    #[track_caller]
464    pub fn unwrap_name(self) -> String {
465        match self {
466            WorldKey::Name(name) => name,
467            WorldKey::Interface(_) => panic!("expected a name, found interface"),
468        }
469    }
470}
471
472#[derive(Debug, Clone, PartialEq)]
473#[cfg_attr(feature = "serde", derive(Serialize))]
474#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
475pub enum WorldItem {
476    Interface {
479        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
480        id: InterfaceId,
481        #[cfg_attr(
482            feature = "serde",
483            serde(skip_serializing_if = "Stability::is_unknown")
484        )]
485        stability: Stability,
486    },
487
488    Function(Function),
490
491    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
495    Type(TypeId),
496}
497
498impl WorldItem {
499    pub fn stability<'a>(&'a self, resolve: &'a Resolve) -> &'a Stability {
500        match self {
501            WorldItem::Interface { stability, .. } => stability,
502            WorldItem::Function(f) => &f.stability,
503            WorldItem::Type(id) => &resolve.types[*id].stability,
504        }
505    }
506}
507
508#[derive(Debug, Clone)]
509#[cfg_attr(feature = "serde", derive(Serialize))]
510pub struct Interface {
511    pub name: Option<String>,
515
516    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
521    pub types: IndexMap<String, TypeId>,
522
523    pub functions: IndexMap<String, Function>,
525
526    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
528    pub docs: Docs,
529
530    #[cfg_attr(
532        feature = "serde",
533        serde(skip_serializing_if = "Stability::is_unknown")
534    )]
535    pub stability: Stability,
536
537    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
539    pub package: Option<PackageId>,
540}
541
542#[derive(Debug, Clone, PartialEq)]
543#[cfg_attr(feature = "serde", derive(Serialize))]
544pub struct TypeDef {
545    pub name: Option<String>,
546    pub kind: TypeDefKind,
547    pub owner: TypeOwner,
548    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
549    pub docs: Docs,
550    #[cfg_attr(
552        feature = "serde",
553        serde(skip_serializing_if = "Stability::is_unknown")
554    )]
555    pub stability: Stability,
556}
557
558#[derive(Debug, Clone, PartialEq)]
559#[cfg_attr(feature = "serde", derive(Serialize))]
560#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
561pub enum TypeDefKind {
562    Record(Record),
563    Resource,
564    Handle(Handle),
565    Flags(Flags),
566    Tuple(Tuple),
567    Variant(Variant),
568    Enum(Enum),
569    Option(Type),
570    Result(Result_),
571    List(Type),
572    Future(Option<Type>),
573    Stream(Option<Type>),
574    Type(Type),
575
576    Unknown,
582}
583
584impl TypeDefKind {
585    pub fn as_str(&self) -> &'static str {
586        match self {
587            TypeDefKind::Record(_) => "record",
588            TypeDefKind::Resource => "resource",
589            TypeDefKind::Handle(handle) => match handle {
590                Handle::Own(_) => "own",
591                Handle::Borrow(_) => "borrow",
592            },
593            TypeDefKind::Flags(_) => "flags",
594            TypeDefKind::Tuple(_) => "tuple",
595            TypeDefKind::Variant(_) => "variant",
596            TypeDefKind::Enum(_) => "enum",
597            TypeDefKind::Option(_) => "option",
598            TypeDefKind::Result(_) => "result",
599            TypeDefKind::List(_) => "list",
600            TypeDefKind::Future(_) => "future",
601            TypeDefKind::Stream(_) => "stream",
602            TypeDefKind::Type(_) => "type",
603            TypeDefKind::Unknown => "unknown",
604        }
605    }
606}
607
608#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
609#[cfg_attr(feature = "serde", derive(Serialize))]
610#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
611pub enum TypeOwner {
612    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
614    World(WorldId),
615    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
617    Interface(InterfaceId),
618    #[cfg_attr(feature = "serde", serde(untagged, serialize_with = "serialize_none"))]
621    None,
622}
623
624#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
625#[cfg_attr(feature = "serde", derive(Serialize))]
626#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
627pub enum Handle {
628    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
629    Own(TypeId),
630    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
631    Borrow(TypeId),
632}
633
634#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
635pub enum Type {
636    Bool,
637    U8,
638    U16,
639    U32,
640    U64,
641    S8,
642    S16,
643    S32,
644    S64,
645    F32,
646    F64,
647    Char,
648    String,
649    ErrorContext,
650    Id(TypeId),
651}
652
653#[derive(Debug, Copy, Clone, Eq, PartialEq)]
654pub enum Int {
655    U8,
656    U16,
657    U32,
658    U64,
659}
660
661#[derive(Debug, Clone, PartialEq)]
662#[cfg_attr(feature = "serde", derive(Serialize))]
663pub struct Record {
664    pub fields: Vec<Field>,
665}
666
667#[derive(Debug, Clone, PartialEq)]
668#[cfg_attr(feature = "serde", derive(Serialize))]
669pub struct Field {
670    pub name: String,
671    #[cfg_attr(feature = "serde", serde(rename = "type"))]
672    pub ty: Type,
673    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
674    pub docs: Docs,
675}
676
677#[derive(Debug, Clone, PartialEq)]
678#[cfg_attr(feature = "serde", derive(Serialize))]
679pub struct Flags {
680    pub flags: Vec<Flag>,
681}
682
683#[derive(Debug, Clone, PartialEq)]
684#[cfg_attr(feature = "serde", derive(Serialize))]
685pub struct Flag {
686    pub name: String,
687    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
688    pub docs: Docs,
689}
690
691#[derive(Debug, Clone, PartialEq)]
692pub enum FlagsRepr {
693    U8,
694    U16,
695    U32(usize),
696}
697
698impl Flags {
699    pub fn repr(&self) -> FlagsRepr {
700        match self.flags.len() {
701            0 => FlagsRepr::U32(0),
702            n if n <= 8 => FlagsRepr::U8,
703            n if n <= 16 => FlagsRepr::U16,
704            n => FlagsRepr::U32(sizealign::align_to(n, 32) / 32),
705        }
706    }
707}
708
709impl FlagsRepr {
710    pub fn count(&self) -> usize {
711        match self {
712            FlagsRepr::U8 => 1,
713            FlagsRepr::U16 => 1,
714            FlagsRepr::U32(n) => *n,
715        }
716    }
717}
718
719#[derive(Debug, Clone, PartialEq)]
720#[cfg_attr(feature = "serde", derive(Serialize))]
721pub struct Tuple {
722    pub types: Vec<Type>,
723}
724
725#[derive(Debug, Clone, PartialEq)]
726#[cfg_attr(feature = "serde", derive(Serialize))]
727pub struct Variant {
728    pub cases: Vec<Case>,
729}
730
731#[derive(Debug, Clone, PartialEq)]
732#[cfg_attr(feature = "serde", derive(Serialize))]
733pub struct Case {
734    pub name: String,
735    #[cfg_attr(feature = "serde", serde(rename = "type"))]
736    pub ty: Option<Type>,
737    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
738    pub docs: Docs,
739}
740
741impl Variant {
742    pub fn tag(&self) -> Int {
743        discriminant_type(self.cases.len())
744    }
745}
746
747#[derive(Debug, Clone, PartialEq)]
748#[cfg_attr(feature = "serde", derive(Serialize))]
749pub struct Enum {
750    pub cases: Vec<EnumCase>,
751}
752
753#[derive(Debug, Clone, PartialEq)]
754#[cfg_attr(feature = "serde", derive(Serialize))]
755pub struct EnumCase {
756    pub name: String,
757    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
758    pub docs: Docs,
759}
760
761impl Enum {
762    pub fn tag(&self) -> Int {
763        discriminant_type(self.cases.len())
764    }
765}
766
767fn discriminant_type(num_cases: usize) -> Int {
769    match num_cases.checked_sub(1) {
770        None => Int::U8,
771        Some(n) if n <= u8::max_value() as usize => Int::U8,
772        Some(n) if n <= u16::max_value() as usize => Int::U16,
773        Some(n) if n <= u32::max_value() as usize => Int::U32,
774        _ => panic!("too many cases to fit in a repr"),
775    }
776}
777
778#[derive(Debug, Clone, PartialEq)]
779#[cfg_attr(feature = "serde", derive(Serialize))]
780pub struct Result_ {
781    pub ok: Option<Type>,
782    pub err: Option<Type>,
783}
784
785#[derive(Clone, Default, Debug, PartialEq, Eq)]
786#[cfg_attr(feature = "serde", derive(Serialize))]
787pub struct Docs {
788    pub contents: Option<String>,
789}
790
791impl Docs {
792    pub fn is_empty(&self) -> bool {
793        self.contents.is_none()
794    }
795}
796
797#[derive(Debug, Clone, PartialEq, Eq)]
798#[cfg_attr(feature = "serde", derive(Serialize))]
799pub struct Function {
800    pub name: String,
801    pub kind: FunctionKind,
802    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_params"))]
803    pub params: Vec<(String, Type)>,
804    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
805    pub result: Option<Type>,
806    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
807    pub docs: Docs,
808    #[cfg_attr(
810        feature = "serde",
811        serde(skip_serializing_if = "Stability::is_unknown")
812    )]
813    pub stability: Stability,
814}
815
816#[derive(Debug, Clone, PartialEq, Eq)]
817#[cfg_attr(feature = "serde", derive(Serialize))]
818#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
819pub enum FunctionKind {
820    Freestanding,
828
829    AsyncFreestanding,
837
838    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
849    Method(TypeId),
850
851    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
862    AsyncMethod(TypeId),
863
864    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
874    Static(TypeId),
875
876    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
886    AsyncStatic(TypeId),
887
888    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
898    Constructor(TypeId),
899}
900
901impl FunctionKind {
902    pub fn resource(&self) -> Option<TypeId> {
904        match self {
905            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
906            FunctionKind::Method(id)
907            | FunctionKind::Static(id)
908            | FunctionKind::Constructor(id)
909            | FunctionKind::AsyncMethod(id)
910            | FunctionKind::AsyncStatic(id) => Some(*id),
911        }
912    }
913
914    pub fn resource_mut(&mut self) -> Option<&mut TypeId> {
916        match self {
917            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
918            FunctionKind::Method(id)
919            | FunctionKind::Static(id)
920            | FunctionKind::Constructor(id)
921            | FunctionKind::AsyncMethod(id)
922            | FunctionKind::AsyncStatic(id) => Some(id),
923        }
924    }
925}
926
927#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
929pub enum Mangling {
930    Standard32,
933
934    Legacy,
939}
940
941impl std::str::FromStr for Mangling {
942    type Err = anyhow::Error;
943
944    fn from_str(s: &str) -> Result<Mangling> {
945        match s {
946            "legacy" => Ok(Mangling::Legacy),
947            "standard32" => Ok(Mangling::Standard32),
948            _ => {
949                bail!(
950                    "unknown name mangling `{s}`, \
951                     supported values are `legacy` or `standard32`"
952                )
953            }
954        }
955    }
956}
957
958#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
960pub enum LiftLowerAbi {
961    Sync,
963
964    AsyncCallback,
967
968    AsyncStackful,
971}
972
973impl LiftLowerAbi {
974    fn import_prefix(self) -> &'static str {
975        match self {
976            Self::Sync => "",
977            Self::AsyncCallback | Self::AsyncStackful => "[async-lower]",
978        }
979    }
980
981    pub fn import_variant(self) -> AbiVariant {
983        match self {
984            Self::Sync => AbiVariant::GuestImport,
985            Self::AsyncCallback | Self::AsyncStackful => AbiVariant::GuestImportAsync,
986        }
987    }
988
989    fn export_prefix(self) -> &'static str {
990        match self {
991            Self::Sync => "",
992            Self::AsyncCallback => "[async-lift]",
993            Self::AsyncStackful => "[async-lift-stackful]",
994        }
995    }
996
997    pub fn export_variant(self) -> AbiVariant {
999        match self {
1000            Self::Sync => AbiVariant::GuestExport,
1001            Self::AsyncCallback => AbiVariant::GuestExportAsync,
1002            Self::AsyncStackful => AbiVariant::GuestExportAsyncStackful,
1003        }
1004    }
1005}
1006
1007#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1009pub enum ManglingAndAbi {
1010    Standard32,
1015
1016    Legacy(LiftLowerAbi),
1018}
1019
1020impl ManglingAndAbi {
1021    pub fn import_variant(self) -> AbiVariant {
1023        match self {
1024            Self::Standard32 => AbiVariant::GuestImport,
1025            Self::Legacy(abi) => abi.import_variant(),
1026        }
1027    }
1028
1029    pub fn export_variant(self) -> AbiVariant {
1031        match self {
1032            Self::Standard32 => AbiVariant::GuestExport,
1033            Self::Legacy(abi) => abi.export_variant(),
1034        }
1035    }
1036
1037    pub fn sync(self) -> Self {
1039        match self {
1040            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => self,
1041            Self::Legacy(LiftLowerAbi::AsyncCallback)
1042            | Self::Legacy(LiftLowerAbi::AsyncStackful) => Self::Legacy(LiftLowerAbi::Sync),
1043        }
1044    }
1045}
1046
1047impl Function {
1048    pub fn item_name(&self) -> &str {
1049        match &self.kind {
1050            FunctionKind::Freestanding => &self.name,
1051            FunctionKind::AsyncFreestanding => &self.name["[async]".len()..],
1052            FunctionKind::Method(_)
1053            | FunctionKind::Static(_)
1054            | FunctionKind::AsyncMethod(_)
1055            | FunctionKind::AsyncStatic(_) => &self.name[self.name.find('.').unwrap() + 1..],
1056            FunctionKind::Constructor(_) => "constructor",
1057        }
1058    }
1059
1060    pub fn parameter_and_result_types(&self) -> impl Iterator<Item = Type> + '_ {
1065        self.params.iter().map(|(_, t)| *t).chain(self.result)
1066    }
1067
1068    pub fn standard32_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1070        self.core_export_name(interface, Mangling::Standard32)
1071    }
1072
1073    pub fn legacy_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1074        self.core_export_name(interface, Mangling::Legacy)
1075    }
1076    pub fn core_export_name<'a>(
1078        &'a self,
1079        interface: Option<&str>,
1080        mangling: Mangling,
1081    ) -> Cow<'a, str> {
1082        match interface {
1083            Some(interface) => match mangling {
1084                Mangling::Standard32 => Cow::Owned(format!("cm32p2|{interface}|{}", self.name)),
1085                Mangling::Legacy => Cow::Owned(format!("{interface}#{}", self.name)),
1086            },
1087            None => match mangling {
1088                Mangling::Standard32 => Cow::Owned(format!("cm32p2||{}", self.name)),
1089                Mangling::Legacy => Cow::Borrowed(&self.name),
1090            },
1091        }
1092    }
1093    pub fn find_futures_and_streams(&self, resolve: &Resolve) -> Vec<TypeId> {
1109        let mut results = Vec::new();
1110        for (_, ty) in self.params.iter() {
1111            find_futures_and_streams(resolve, *ty, &mut results);
1112        }
1113        if let Some(ty) = self.result {
1114            find_futures_and_streams(resolve, ty, &mut results);
1115        }
1116        results
1117    }
1118}
1119
1120fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeId>) {
1121    let Type::Id(id) = ty else {
1122        return;
1123    };
1124
1125    match &resolve.types[id].kind {
1126        TypeDefKind::Resource
1127        | TypeDefKind::Handle(_)
1128        | TypeDefKind::Flags(_)
1129        | TypeDefKind::Enum(_) => {}
1130        TypeDefKind::Record(r) => {
1131            for Field { ty, .. } in &r.fields {
1132                find_futures_and_streams(resolve, *ty, results);
1133            }
1134        }
1135        TypeDefKind::Tuple(t) => {
1136            for ty in &t.types {
1137                find_futures_and_streams(resolve, *ty, results);
1138            }
1139        }
1140        TypeDefKind::Variant(v) => {
1141            for Case { ty, .. } in &v.cases {
1142                if let Some(ty) = ty {
1143                    find_futures_and_streams(resolve, *ty, results);
1144                }
1145            }
1146        }
1147        TypeDefKind::Option(ty) | TypeDefKind::List(ty) | TypeDefKind::Type(ty) => {
1148            find_futures_and_streams(resolve, *ty, results);
1149        }
1150        TypeDefKind::Result(r) => {
1151            if let Some(ty) = r.ok {
1152                find_futures_and_streams(resolve, ty, results);
1153            }
1154            if let Some(ty) = r.err {
1155                find_futures_and_streams(resolve, ty, results);
1156            }
1157        }
1158        TypeDefKind::Future(ty) => {
1159            if let Some(ty) = ty {
1160                find_futures_and_streams(resolve, *ty, results);
1161            }
1162            results.push(id);
1163        }
1164        TypeDefKind::Stream(ty) => {
1165            if let Some(ty) = ty {
1166                find_futures_and_streams(resolve, *ty, results);
1167            }
1168            results.push(id);
1169        }
1170        TypeDefKind::Unknown => unreachable!(),
1171    }
1172}
1173
1174#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1182#[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
1183#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1184pub enum Stability {
1185    Unknown,
1187
1188    Unstable {
1193        feature: String,
1194        #[cfg_attr(
1195            feature = "serde",
1196            serde(
1197                skip_serializing_if = "Option::is_none",
1198                default,
1199                serialize_with = "serialize_optional_version",
1200                deserialize_with = "deserialize_optional_version"
1201            )
1202        )]
1203        deprecated: Option<Version>,
1204    },
1205
1206    Stable {
1211        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_version"))]
1212        #[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_version"))]
1213        since: Version,
1214        #[cfg_attr(
1215            feature = "serde",
1216            serde(
1217                skip_serializing_if = "Option::is_none",
1218                default,
1219                serialize_with = "serialize_optional_version",
1220                deserialize_with = "deserialize_optional_version"
1221            )
1222        )]
1223        deprecated: Option<Version>,
1224    },
1225}
1226
1227impl Stability {
1228    pub fn is_unknown(&self) -> bool {
1230        matches!(self, Stability::Unknown)
1231    }
1232}
1233
1234impl Default for Stability {
1235    fn default() -> Stability {
1236        Stability::Unknown
1237    }
1238}
1239
1240#[cfg(test)]
1241mod test {
1242    use super::*;
1243
1244    #[test]
1245    fn test_discriminant_type() {
1246        assert_eq!(discriminant_type(1), Int::U8);
1247        assert_eq!(discriminant_type(0x100), Int::U8);
1248        assert_eq!(discriminant_type(0x101), Int::U16);
1249        assert_eq!(discriminant_type(0x10000), Int::U16);
1250        assert_eq!(discriminant_type(0x10001), Int::U32);
1251        if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
1252            assert_eq!(discriminant_type(num_cases), Int::U32);
1253        }
1254    }
1255
1256    #[test]
1257    fn test_find_futures_and_streams() {
1258        let mut resolve = Resolve::default();
1259        let t0 = resolve.types.alloc(TypeDef {
1260            name: None,
1261            kind: TypeDefKind::Future(Some(Type::U32)),
1262            owner: TypeOwner::None,
1263            docs: Docs::default(),
1264            stability: Stability::Unknown,
1265        });
1266        let t1 = resolve.types.alloc(TypeDef {
1267            name: None,
1268            kind: TypeDefKind::Future(Some(Type::Id(t0))),
1269            owner: TypeOwner::None,
1270            docs: Docs::default(),
1271            stability: Stability::Unknown,
1272        });
1273        let t2 = resolve.types.alloc(TypeDef {
1274            name: None,
1275            kind: TypeDefKind::Stream(Some(Type::U32)),
1276            owner: TypeOwner::None,
1277            docs: Docs::default(),
1278            stability: Stability::Unknown,
1279        });
1280        let found = Function {
1281            name: "foo".into(),
1282            kind: FunctionKind::Freestanding,
1283            params: vec![("p1".into(), Type::Id(t1)), ("p2".into(), Type::U32)],
1284            result: Some(Type::Id(t2)),
1285            docs: Docs::default(),
1286            stability: Stability::Unknown,
1287        }
1288        .find_futures_and_streams(&resolve);
1289        assert_eq!(3, found.len());
1290        assert_eq!(t0, found[0]);
1291        assert_eq!(t1, found[1]);
1292        assert_eq!(t2, found[2]);
1293    }
1294}