1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use std::{
    fmt::{Debug, Display, Formatter},
    hash::Hash,
    sync::Arc,
};

use semver::Version;

mod convert;
mod display;

/// e.g.: `wasi:random`
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WasiPublisher {
    organization: Arc<str>,
    project: Arc<str>,
}

/// e.g: `wasi:random/random@0.2.0`
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct WasiModule {
    pub package: Option<WasiPublisher>,
    pub name: Arc<str>,
    pub version: Option<Version>,
}

impl WasiModule {
    /// Create a new module without a publisher
    pub fn new<S>(name: S) -> Self
    where
        S: Into<Arc<str>>,
    {
        let name = name.into();
        if name.contains(&['/', ':']) {
            panic!("Invalid module name: {}", name);
        }
        Self { package: None, name: name.into(), version: None }
    }
    /// Set the publisher for the module
    pub fn with_publisher(self, publisher: WasiPublisher) -> Self {
        Self { package: Some(publisher), ..self }
    }
    /// Set the version for the module
    pub fn with_version(self, version: Version) -> Self {
        Self { version: Some(version), ..self }
    }
    /// Set the organization and project for the module
    pub fn with_project<O, P>(self, organization: O, project: P) -> Self
    where
        O: Into<Arc<str>>,
        P: Into<Arc<str>>,
    {
        Self { package: Some(WasiPublisher { organization: organization.into(), project: project.into() }), ..self }
    }
}