wasmhub 0.1.4

Download and manage WebAssembly runtimes for multiple languages
Documentation
use std::fmt;
use std::path::PathBuf;
use std::str::FromStr;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Language {
    NodeJs,
    Python,
    Ruby,
    Php,
    Go,
    Rust,
}

impl Language {
    pub fn as_str(&self) -> &'static str {
        match self {
            Language::NodeJs => "nodejs",
            Language::Python => "python",
            Language::Ruby => "ruby",
            Language::Php => "php",
            Language::Go => "go",
            Language::Rust => "rust",
        }
    }

    pub fn all() -> &'static [Language] {
        &[
            Language::NodeJs,
            Language::Python,
            Language::Ruby,
            Language::Php,
            Language::Go,
            Language::Rust,
        ]
    }
}

impl FromStr for Language {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "nodejs" | "node" | "node.js" => Ok(Language::NodeJs),
            "python" | "py" => Ok(Language::Python),
            "ruby" | "rb" => Ok(Language::Ruby),
            "php" => Ok(Language::Php),
            "go" | "golang" => Ok(Language::Go),
            "rust" | "rs" => Ok(Language::Rust),
            _ => Err(format!("Unknown language: {s}")),
        }
    }
}

impl fmt::Display for Language {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Runtime {
    pub language: Language,
    pub version: String,
    pub path: PathBuf,
    pub size: u64,
    pub sha256: String,
}

impl Runtime {
    pub fn new(
        language: Language,
        version: String,
        path: PathBuf,
        size: u64,
        sha256: String,
    ) -> Self {
        Self {
            language,
            version,
            path,
            size,
            sha256,
        }
    }

    pub fn filename(&self) -> String {
        format!("{}-{}.wasm", self.language.as_str(), self.version)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_language_from_str() {
        assert_eq!("nodejs".parse::<Language>().unwrap(), Language::NodeJs);
        assert_eq!("node".parse::<Language>().unwrap(), Language::NodeJs);
        assert_eq!("node.js".parse::<Language>().unwrap(), Language::NodeJs);
        assert_eq!("python".parse::<Language>().unwrap(), Language::Python);
        assert_eq!("py".parse::<Language>().unwrap(), Language::Python);
        assert_eq!("ruby".parse::<Language>().unwrap(), Language::Ruby);
        assert_eq!("rb".parse::<Language>().unwrap(), Language::Ruby);
        assert_eq!("php".parse::<Language>().unwrap(), Language::Php);
        assert_eq!("go".parse::<Language>().unwrap(), Language::Go);
        assert_eq!("golang".parse::<Language>().unwrap(), Language::Go);
        assert_eq!("rust".parse::<Language>().unwrap(), Language::Rust);
        assert_eq!("rs".parse::<Language>().unwrap(), Language::Rust);

        assert!("unknown".parse::<Language>().is_err());
        assert!("javascript".parse::<Language>().is_err());
    }

    #[test]
    fn test_language_as_str() {
        assert_eq!(Language::NodeJs.as_str(), "nodejs");
        assert_eq!(Language::Python.as_str(), "python");
        assert_eq!(Language::Ruby.as_str(), "ruby");
        assert_eq!(Language::Php.as_str(), "php");
        assert_eq!(Language::Go.as_str(), "go");
        assert_eq!(Language::Rust.as_str(), "rust");
    }

    #[test]
    fn test_language_display() {
        assert_eq!(format!("{}", Language::NodeJs), "nodejs");
        assert_eq!(format!("{}", Language::Python), "python");
    }

    #[test]
    fn test_runtime_new() {
        let runtime = Runtime::new(
            Language::Python,
            "3.11.7".to_string(),
            PathBuf::from("/cache/python-3.11.7.wasm"),
            1024,
            "abc123".to_string(),
        );

        assert_eq!(runtime.language, Language::Python);
        assert_eq!(runtime.version, "3.11.7");
        assert_eq!(runtime.size, 1024);
        assert_eq!(runtime.sha256, "abc123");
    }

    #[test]
    fn test_runtime_filename() {
        let runtime = Runtime::new(
            Language::NodeJs,
            "20.2.0".to_string(),
            PathBuf::from("/cache/nodejs-20.2.0.wasm"),
            2048,
            "def456".to_string(),
        );

        assert_eq!(runtime.filename(), "nodejs-20.2.0.wasm");
    }

    #[test]
    fn test_language_all() {
        let languages = Language::all();
        assert_eq!(languages.len(), 6);
        assert!(languages.contains(&Language::NodeJs));
        assert!(languages.contains(&Language::Python));
        assert!(languages.contains(&Language::Ruby));
        assert!(languages.contains(&Language::Php));
        assert!(languages.contains(&Language::Go));
        assert!(languages.contains(&Language::Rust));
    }
}