Skip to main content

platform_module/
host.rs

1use crate::{LinkedBinding, Module, ModuleManifest};
2use platform_core::{AppContext, Migration};
3use std::any::{Any, TypeId};
4use std::sync::Arc;
5
6#[derive(Clone)]
7pub struct HostContribution {
8    type_id: TypeId,
9    value: Arc<dyn Any + Send + Sync>,
10}
11
12impl std::fmt::Debug for HostContribution {
13    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        formatter
15            .debug_struct("HostContribution")
16            .field("type_id", &self.type_id)
17            .finish_non_exhaustive()
18    }
19}
20
21impl HostContribution {
22    pub fn typed<T>(value: T) -> Self
23    where
24        T: Send + Sync + 'static,
25    {
26        Self {
27            type_id: TypeId::of::<T>(),
28            value: Arc::new(value),
29        }
30    }
31
32    pub fn get<T>(&self) -> Option<&T>
33    where
34        T: Send + Sync + 'static,
35    {
36        (self.type_id == TypeId::of::<T>())
37            .then(|| self.value.downcast_ref::<T>())
38            .flatten()
39    }
40}
41
42#[derive(Debug, Clone)]
43pub struct HostLinkedModule {
44    pub module_name: &'static str,
45    pub manifest: fn() -> ModuleManifest,
46    pub load: Option<fn(&AppContext) -> Module>,
47    pub http_binding: Option<fn() -> LinkedBinding>,
48    pub migrations: &'static [Migration],
49    contributions: Vec<HostContribution>,
50}
51
52impl HostLinkedModule {
53    #[must_use]
54    pub fn manifest_only(
55        module_name: &'static str,
56        manifest: fn() -> ModuleManifest,
57        migrations: &'static [Migration],
58    ) -> Self {
59        Self {
60            module_name,
61            manifest,
62            load: None,
63            http_binding: None,
64            migrations,
65            contributions: Vec::new(),
66        }
67    }
68
69    #[must_use]
70    pub fn linked(
71        module_name: &'static str,
72        manifest: fn() -> ModuleManifest,
73        load: fn(&AppContext) -> Module,
74        migrations: &'static [Migration],
75    ) -> Self {
76        Self {
77            module_name,
78            manifest,
79            load: Some(load),
80            http_binding: None,
81            migrations,
82            contributions: Vec::new(),
83        }
84    }
85
86    #[must_use]
87    pub fn with_http_binding(mut self, http_binding: fn() -> LinkedBinding) -> Self {
88        self.http_binding = Some(http_binding);
89        self
90    }
91
92    #[must_use]
93    pub fn with_contribution<T>(mut self, contribution: T) -> Self
94    where
95        T: Send + Sync + 'static,
96    {
97        self.contributions
98            .push(HostContribution::typed(contribution));
99        self
100    }
101
102    pub fn contributions<T>(&self) -> impl Iterator<Item = &T>
103    where
104        T: Send + Sync + 'static,
105    {
106        self.contributions
107            .iter()
108            .filter_map(HostContribution::get::<T>)
109    }
110}