Skip to main content

hara_native/lang/protocol/
declarations.rs

1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2pub enum ProtocolAvailability {
3    Portable,
4    CapabilityGated,
5    InventoryOnly,
6}
7
8impl ProtocolAvailability {
9    pub fn is_guest_visible(self) -> bool {
10        !matches!(self, Self::InventoryOnly)
11    }
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum ProtocolArity {
16    Fixed(usize),
17    Variadic {
18        minimum: usize,
19        maximum: Option<usize>,
20    },
21}
22
23impl ProtocolArity {
24    pub fn guest_arity(self) -> usize {
25        match self {
26            Self::Fixed(arity) => arity,
27            Self::Variadic { .. } => usize::MAX,
28        }
29    }
30
31    pub fn range(self) -> (usize, Option<usize>) {
32        match self {
33            Self::Fixed(arity) => (arity, Some(arity)),
34            Self::Variadic { minimum, maximum } => (minimum, maximum),
35        }
36    }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub struct ProtocolMethodDeclaration {
41    pub name: &'static str,
42    pub rust_name: &'static str,
43    pub arity: ProtocolArity,
44    pub whole_wasm: bool,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub struct ProtocolDeclaration {
49    pub namespace: &'static str,
50    pub name: &'static str,
51    pub parents: &'static [&'static str],
52    pub availability: ProtocolAvailability,
53    pub capability: Option<&'static str>,
54    pub methods: &'static [ProtocolMethodDeclaration],
55}
56
57impl ProtocolDeclaration {
58    pub fn qualified_name(self) -> String {
59        format!("{}/{}", self.namespace, self.name)
60    }
61
62    pub fn runtime_name(self) -> String {
63        format!("{}.{}", self.namespace, self.name)
64    }
65
66    pub fn method(self, name: &str) -> Option<ProtocolMethodDeclaration> {
67        self.methods
68            .iter()
69            .copied()
70            .find(|method| method.name == name)
71    }
72}
73
74inventory::collect!(ProtocolDeclaration);
75
76static PROTOCOL_DECLARATIONS: std::sync::OnceLock<Vec<ProtocolDeclaration>> =
77    std::sync::OnceLock::new();
78
79pub fn protocol_declarations() -> &'static [ProtocolDeclaration] {
80    PROTOCOL_DECLARATIONS
81        .get_or_init(|| {
82            let mut declarations = inventory::iter::<ProtocolDeclaration>
83                .into_iter()
84                .copied()
85                .collect::<Vec<_>>();
86            declarations.sort_by_key(|declaration| (declaration.namespace, declaration.name));
87            declarations
88        })
89        .as_slice()
90}
91
92pub fn find_protocol(name: &str) -> Option<ProtocolDeclaration> {
93    protocol_declarations().iter().copied().find(|protocol| {
94        protocol.name == name
95            || protocol.qualified_name() == name
96            || protocol.runtime_name() == name
97    })
98}