Skip to main content

surrealdb_expr/expr/
module.rs

1use std::fmt::{self, Display};
2
3use anyhow::Result;
4use common::fail;
5use surrealdb_types::{SqlFormat, ToSql};
6
7use crate::expr::Kind;
8use crate::sql;
9use crate::val::File;
10
11#[derive(Clone, Debug, Eq, PartialEq, Hash)]
12pub enum ModuleExecutable {
13	Surrealism(SurrealismExecutable),
14	Silo(SiloExecutable),
15}
16
17impl ToSql for ModuleExecutable {
18	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
19		let module_executable: crate::sql::ModuleExecutable = self.clone().into();
20		module_executable.fmt_sql(f, sql_fmt);
21	}
22}
23
24#[derive(Clone, Debug, Eq, PartialEq, Hash)]
25pub struct Signature {
26	pub args: Vec<Kind>,
27	pub returns: Option<Kind>,
28	pub writeable: bool,
29}
30
31#[derive(Clone, Debug, Eq, PartialEq, Hash)]
32pub struct SurrealismExecutable(pub File);
33
34impl ToSql for SurrealismExecutable {
35	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
36		let surrealism_executable: crate::sql::SurrealismExecutable = self.clone().into();
37		surrealism_executable.fmt_sql(f, sql_fmt);
38	}
39}
40
41#[derive(Clone, Debug, Eq, PartialEq, Hash)]
42pub struct SiloExecutable {
43	pub organisation: String,
44	pub package: String,
45	pub major: u32,
46	pub minor: u32,
47	pub patch: u32,
48}
49
50impl ToSql for SiloExecutable {
51	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
52		let silo_executable: crate::sql::SiloExecutable = self.clone().into();
53		silo_executable.fmt_sql(f, sql_fmt);
54	}
55}
56
57/// The parsed name of a module: a plain module or a silo package release.
58///
59/// Not persisted itself; [`ModuleName::get_storage_name`] is the single point
60/// that derives the storage name both the statements and the catalog use.
61#[derive(Clone, Debug, Eq, PartialEq, Hash)]
62pub enum ModuleName {
63	Module(String),
64	Silo(String, String, u32, u32, u32),
65}
66
67impl ModuleName {
68	pub fn get_storage_name(&self) -> String {
69		match self {
70			ModuleName::Module(name) => format!("mod::{}", name),
71			ModuleName::Silo(org, pkg, major, minor, patch) => {
72				format!("silo::{org}::{pkg}::<{major}.{minor}.{patch}>")
73			}
74		}
75	}
76}
77
78impl From<sql::module::ModuleName> for ModuleName {
79	fn from(v: sql::module::ModuleName) -> Self {
80		match v {
81			sql::module::ModuleName::Module(name) => ModuleName::Module(name),
82			sql::module::ModuleName::Silo(org, pkg, major, minor, patch) => {
83				ModuleName::Silo(org, pkg, major, minor, patch)
84			}
85		}
86	}
87}
88
89impl From<ModuleName> for sql::module::ModuleName {
90	fn from(v: ModuleName) -> Self {
91		match v {
92			ModuleName::Module(name) => sql::module::ModuleName::Module(name),
93			ModuleName::Silo(org, pkg, major, minor, patch) => {
94				sql::module::ModuleName::Silo(org, pkg, major, minor, patch)
95			}
96		}
97	}
98}
99
100impl<'a> TryFrom<&'a crate::expr::statements::DefineModuleStatement> for ModuleName {
101	type Error = anyhow::Error;
102	fn try_from(
103		value: &'a crate::expr::statements::DefineModuleStatement,
104	) -> Result<Self, Self::Error> {
105		if let Some(name) = &value.name {
106			Ok(ModuleName::Module(name.clone()))
107		} else if let crate::expr::ModuleExecutable::Silo(silo) = &value.executable {
108			Ok(ModuleName::Silo(
109				silo.organisation.clone(),
110				silo.package.clone(),
111				silo.major,
112				silo.minor,
113				silo.patch,
114			))
115		} else {
116			// It should not be possible to get to this point as in the parser
117			// we validate that the module has a name or is a silo module
118			fail!("A module without a name cannot be stored")
119		}
120	}
121}
122
123impl Display for ModuleName {
124	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125		match self {
126			ModuleName::Module(name) => write!(f, "mod::{}", name),
127			ModuleName::Silo(org, pkg, major, minor, patch) => {
128				write!(f, "silo::{org}::{pkg}::<{major}.{minor}.{patch}>")
129			}
130		}
131	}
132}