1use std::{
2 any::TypeId,
3 marker::PhantomData,
4 sync::{Arc, Weak},
5};
6
7use crate::{Result, runtime::Runtime};
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
10pub(crate) struct ServiceId {
11 pub key: TypeId,
12 pub isolation: u64,
13}
14
15impl ServiceId {
16 pub fn root(key: TypeId) -> Self {
17 Self { key, isolation: 0 }
18 }
19}
20
21pub trait ServiceKey: Send + Sync + 'static {
24 type Value: ?Sized + Send + Sync + 'static;
25 const NAME: &'static str;
26}
27
28#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub struct ServiceDeclaration {
30 pub(crate) key: TypeId,
31 pub name: &'static str,
32}
33
34impl ServiceDeclaration {
35 pub fn of<K: ServiceKey>() -> Self {
36 Self {
37 key: TypeId::of::<K>(),
38 name: K::NAME,
39 }
40 }
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub struct Dependency {
45 pub(crate) key: TypeId,
46 pub name: &'static str,
47 pub required: bool,
48}
49
50impl Dependency {
51 pub fn required<K: ServiceKey>() -> Self {
52 Self {
53 key: TypeId::of::<K>(),
54 name: K::NAME,
55 required: true,
56 }
57 }
58
59 pub fn optional<K: ServiceKey>() -> Self {
60 Self {
61 key: TypeId::of::<K>(),
62 name: K::NAME,
63 required: false,
64 }
65 }
66}
67
68pub struct ServiceHandle<K: ServiceKey> {
71 pub(crate) runtime: Weak<Runtime>,
72 pub(crate) id: ServiceId,
73 pub(crate) owner: u64,
74 pub(crate) token: u64,
75 pub(crate) _key: PhantomData<fn() -> K>,
76}
77
78impl<K: ServiceKey> ServiceHandle<K> {
79 pub fn replace(&self, value: Arc<K::Value>) -> Result<u64> {
80 let runtime = self.runtime.upgrade().ok_or(crate::Error::PluginDisposed)?;
81 runtime.replace_service::<K>(self.id, self.owner, self.token, value)
82 }
83
84 pub fn touch(&self) -> Result<u64> {
85 let runtime = self.runtime.upgrade().ok_or(crate::Error::PluginDisposed)?;
86 runtime.touch_service::<K>(self.id, self.owner, self.token)
87 }
88
89 pub fn remove(&self) -> bool {
91 self.runtime
92 .upgrade()
93 .is_some_and(|runtime| runtime.remove_service(self.id, self.owner, self.token))
94 }
95}
96
97pub(crate) struct ServiceEntry {
98 pub value: Box<dyn std::any::Any + Send + Sync>,
99 pub owner: u64,
100 pub token: u64,
101 pub generation: u64,
102 pub name: &'static str,
103 pub active: bool,
104}
105
106pub(crate) fn boxed_service<K: ServiceKey>(
107 value: Arc<K::Value>,
108) -> Box<dyn std::any::Any + Send + Sync> {
109 Box::new(value)
110}