#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct FnId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct TypeId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct CtorId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ModuleId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct BuiltinId(pub u32);
impl ModuleId {
pub const ENTRY: ModuleId = ModuleId(0);
pub fn is_entry(self) -> bool {
self == Self::ENTRY
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct FnKey {
pub scope: Option<String>,
pub name: String,
}
impl FnKey {
pub fn entry(name: impl Into<String>) -> Self {
Self {
scope: None,
name: name.into(),
}
}
pub fn in_module(prefix: impl Into<String>, name: impl Into<String>) -> Self {
Self {
scope: Some(prefix.into()),
name: name.into(),
}
}
pub fn canonical(&self) -> String {
match &self.scope {
Some(prefix) => format!("{}.{}", prefix, self.name),
None => self.name.clone(),
}
}
pub fn scope_str(&self) -> Option<&str> {
self.scope.as_deref()
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct TypeKey {
pub scope: Option<String>,
pub name: String,
}
impl TypeKey {
pub fn entry(name: impl Into<String>) -> Self {
Self {
scope: None,
name: name.into(),
}
}
pub fn in_module(prefix: impl Into<String>, name: impl Into<String>) -> Self {
Self {
scope: Some(prefix.into()),
name: name.into(),
}
}
pub fn canonical(&self) -> String {
match &self.scope {
Some(prefix) => format!("{}.{}", prefix, self.name),
None => self.name.clone(),
}
}
pub fn scope_str(&self) -> Option<&str> {
self.scope.as_deref()
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct LawKey {
pub fn_key: FnKey,
pub law_name: String,
}
impl LawKey {
pub fn new(fn_key: FnKey, law_name: impl Into<String>) -> Self {
Self {
fn_key,
law_name: law_name.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fn_key_canonical_distinguishes_entry_from_module() {
let entry = FnKey::entry("foo");
let in_a = FnKey::in_module("A", "foo");
let in_b = FnKey::in_module("B", "foo");
assert_eq!(entry.canonical(), "foo");
assert_eq!(in_a.canonical(), "A.foo");
assert_eq!(in_b.canonical(), "B.foo");
assert_ne!(entry, in_a);
assert_ne!(in_a, in_b);
}
#[test]
fn nested_module_prefix_round_trips_through_canonical() {
let key = FnKey::in_module("Models.User", "freshId");
assert_eq!(key.canonical(), "Models.User.freshId");
assert_eq!(key.scope_str(), Some("Models.User"));
}
}