wire_framework/
wiring_layer.rs1use std::fmt;
2
3use tokio::runtime;
4
5use crate::{FromContext, IntoContext, resource::ResourceId, service::ServiceContext};
6
7#[allow(clippy::type_complexity)] pub(crate) struct WireFn(
14 pub Box<dyn FnOnce(&runtime::Handle, &mut ServiceContext<'_>) -> Result<(), WiringError>>,
15);
16
17impl fmt::Debug for WireFn {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 f.debug_struct("WireFn").finish()
20 }
21}
22
23#[async_trait::async_trait]
29pub trait WiringLayer: 'static + Send + Sync {
30 type Input: FromContext;
31 type Output: IntoContext;
32
33 fn layer_name(&self) -> &'static str;
35
36 async fn wire(self, input: Self::Input) -> Result<Self::Output, WiringError>;
39}
40
41pub(crate) trait WiringLayerExt: WiringLayer {
42 fn into_wire_fn(self) -> WireFn
45 where
46 Self: Sized,
47 {
48 WireFn(Box::new(move |rt, ctx| {
49 let input = Self::Input::from_context(ctx)?;
50 let output = rt.block_on(self.wire(input))?;
51 output.into_context(ctx)?;
52 Ok(())
53 }))
54 }
55}
56
57impl<T> WiringLayerExt for T where T: WiringLayer {}
58
59#[derive(thiserror::Error, Debug)]
61#[non_exhaustive]
62pub enum WiringError {
63 #[error("Layer attempted to add resource {name}, but it is already provided")]
64 ResourceAlreadyProvided { id: ResourceId, name: String },
65 #[error("Resource {name} is not provided")]
66 ResourceLacking { id: ResourceId, name: String },
67 #[error("Wiring layer has been incorrectly configured: {0}")]
68 Configuration(String),
69 #[error(transparent)]
70 Internal(#[from] eyre::Report),
71}
72
73impl WiringError {
74 pub fn internal(err: impl Into<eyre::Report>) -> Self {
76 Self::Internal(err.into())
77 }
78}