Skip to main content

microde_application/
composition.rs

1use std::fmt::{self, Debug, Formatter};
2use std::marker::PhantomData;
3
4use crate::MicrodeModule;
5
6/// Stable identity of one installed module instance.
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct ModuleInstanceId(String);
9
10impl ModuleInstanceId {
11    pub fn new(value: impl Into<String>) -> Self {
12        Self(value.into())
13    }
14
15    pub fn as_str(&self) -> &str {
16        &self.0
17    }
18}
19
20/// Opaque binding target for one installed module instance.
21pub struct ModuleHandle<Module: MicrodeModule> {
22    id: ModuleInstanceId,
23    pub(crate) owner: u64,
24    module: PhantomData<fn() -> Module>,
25}
26
27#[doc(hidden)]
28pub trait ModuleHandleIdentity {
29    fn module_instance_id(&self) -> &ModuleInstanceId;
30    fn composition_owner(&self) -> u64;
31}
32
33impl<Module: MicrodeModule> Debug for ModuleHandle<Module> {
34    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
35        formatter
36            .debug_struct("ModuleHandle")
37            .field("id", &self.id)
38            .finish_non_exhaustive()
39    }
40}
41
42impl<Module: MicrodeModule> ModuleHandle<Module> {
43    pub(crate) fn new(id: ModuleInstanceId, owner: u64) -> Self {
44        Self {
45            id,
46            owner,
47            module: PhantomData,
48        }
49    }
50
51    pub fn id(&self) -> &ModuleInstanceId {
52        &self.id
53    }
54}
55
56impl<Module: MicrodeModule> ModuleHandleIdentity for ModuleHandle<Module> {
57    fn module_instance_id(&self) -> &ModuleInstanceId {
58        &self.id
59    }
60    fn composition_owner(&self) -> u64 {
61        self.owner
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use crate::{Dependency, Port, Reference};
68
69    trait Database: Send + Sync {}
70
71    #[test]
72    fn declares_independent_typed_relationship_slots() {
73        let port = Port::<dyn Database>::new("database");
74        let first = Dependency::new("database", port.clone());
75        let second = Dependency::new("database", port.clone());
76        let peer = Reference::new("peer", port);
77
78        assert_eq!(first.name(), "database");
79        assert_eq!(first.port().description(), "database");
80        assert_ne!(first.slot_id(), second.slot_id());
81        assert_eq!(peer.name(), "peer");
82        assert_eq!(peer.port().description(), "database");
83    }
84}