use std::fmt::{self, Display};
use revision::revisioned;
use crate::catalog::ModuleDefinition;
use crate::expr::statements::info::InfoStructure;
use crate::val::Value;
#[revisioned(revision = 1)]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub(crate) enum ModuleExecutable {
Surrealism(SurrealismExecutable),
Silo(SiloExecutable),
}
impl InfoStructure for ModuleExecutable {
fn structure(self) -> Value {
match self {
ModuleExecutable::Surrealism(surrealism) => surrealism.structure(),
ModuleExecutable::Silo(silo) => silo.structure(),
}
}
}
#[revisioned(revision = 1)]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub(crate) struct SurrealismExecutable {
pub bucket: String,
pub key: String,
}
impl InfoStructure for SurrealismExecutable {
fn structure(self) -> Value {
Value::from(map! {
"type" => Value::from("surrealism"),
"bucket" => self.bucket.into(),
"key" => self.key.into(),
})
}
}
#[revisioned(revision = 1)]
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub(crate) struct SiloExecutable {
pub organisation: String,
pub package: String,
pub major: u32,
pub minor: u32,
pub patch: u32,
}
impl InfoStructure for SiloExecutable {
fn structure(self) -> Value {
Value::from(map! {
"type" => Value::from("silo"),
"organisation" => self.organisation.into(),
"package" => self.package.into(),
"major" => self.major.into(),
"minor" => self.minor.into(),
"patch" => self.patch.into(),
})
}
}
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub(crate) enum ModuleName {
Module(String),
Silo(String, String, u32, u32, u32),
}
impl ModuleName {
pub(crate) fn get_storage_name(&self) -> String {
match self {
ModuleName::Module(name) => format!("mod::{}", name),
ModuleName::Silo(org, pkg, major, minor, patch) => {
format!("silo::{org}::{pkg}<{major}.{minor}.{patch}>")
}
}
}
}
impl TryFrom<&ModuleDefinition> for ModuleName {
type Error = anyhow::Error;
fn try_from(value: &ModuleDefinition) -> Result<Self, Self::Error> {
if let Some(name) = &value.name {
Ok(ModuleName::Module(name.clone()))
} else if let ModuleExecutable::Silo(silo) = &value.executable {
Ok(ModuleName::Silo(
silo.organisation.clone(),
silo.package.clone(),
silo.major,
silo.minor,
silo.patch,
))
} else {
fail!("A module without a name cannot be stored")
}
}
}
impl<'a> TryFrom<&'a crate::expr::statements::DefineModuleStatement> for ModuleName {
type Error = anyhow::Error;
fn try_from(
value: &'a crate::expr::statements::DefineModuleStatement,
) -> Result<Self, Self::Error> {
if let Some(name) = &value.name {
Ok(ModuleName::Module(name.clone()))
} else if let crate::expr::ModuleExecutable::Silo(silo) = &value.executable {
Ok(ModuleName::Silo(
silo.organisation.clone(),
silo.package.clone(),
silo.major,
silo.minor,
silo.patch,
))
} else {
fail!("A module without a name cannot be stored")
}
}
}
impl Display for ModuleName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ModuleName::Module(name) => write!(f, "mod::{}", name),
ModuleName::Silo(org, pkg, major, minor, patch) => {
write!(f, "silo::{org}::{pkg}<{major}.{minor}.{patch}>")
}
}
}
}