Skip to main content

rustolio_utils/
service.rs

1//
2// SPDX-License-Identifier: MPL-2.0
3//
4// Copyright (c) 2026 Tobias Binnewies. All rights reserved.
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9//
10
11pub use rustolio_utils_macros::{Service, service, service_impl};
12pub trait AsStaticRef<T>: AsRef<T> {
13    fn as_static_ref(&'static self) -> &'static T;
14}
15impl<T, R> AsStaticRef<R> for T
16where
17    T: AsRef<R>,
18{
19    fn as_static_ref(&'static self) -> &'static R {
20        self.as_ref()
21    }
22}
23
24/// # Safety
25/// - Must be created at the highest scope
26/// - Must not be moved
27pub struct ServiceLock<S> {
28    ptr: *mut S,
29    _marker: std::marker::PhantomPinned,
30}
31
32impl<S: 'static> ServiceLock<S> {
33    pub fn new(s: S) -> Self {
34        let ptr: &'static mut S = Box::leak(Box::new(s));
35        let ptr = ptr as *mut S;
36        Self {
37            ptr,
38            _marker: std::marker::PhantomPinned,
39        }
40    }
41
42    pub unsafe fn get(&self) -> &'static S { unsafe {
43        // SAFETY: ptr only points to &'static S
44        &*self.ptr as &'static S
45    }}
46}
47
48impl<S> Drop for ServiceLock<S> {
49    fn drop(&mut self) {
50        unsafe {
51            // SAFETY: As long as The ServiceLock is created at the highest scope and not moved somewhere the Box::leak is safe to drop at the end of the application
52            let _ = Box::from_raw(self.ptr);
53        }
54    }
55}