Skip to main content

geam_core/provider/
value.rs

1use crate::HostType;
2use std::marker::PhantomData;
3
4/// A call-scoped opaque handle for one statically declared source type.
5///
6/// Provider macros use this type for generic source values and opaque function
7/// pass-through. It does not expose the concrete runtime family or materialize
8/// the represented value. Use an active [`super::Call`] for source equality,
9/// hashing, and inspection.
10pub struct Value<Type, Context = MissingValueContext> {
11    context: Context,
12    type_: PhantomData<fn() -> Type>,
13}
14
15#[doc(hidden)]
16pub struct MissingValueContext;
17
18/// The exact typed host handle inserted by provider macro expansion.
19#[doc(hidden)]
20pub struct ProviderValueContext<'call, Host>
21where
22    Host: HostType,
23{
24    value: Host::Value<'call>,
25}
26
27impl<'call, Type, Host> Value<Type, ProviderValueContext<'call, Host>>
28where
29    Host: HostType,
30{
31    #[doc(hidden)]
32    pub fn from_host(value: Host::Value<'call>) -> Self {
33        Self {
34            context: ProviderValueContext { value },
35            type_: PhantomData,
36        }
37    }
38
39    #[doc(hidden)]
40    pub fn into_host(self) -> Host::Value<'call> {
41        self.context.value
42    }
43
44    pub(crate) fn host(&self) -> Host::Value<'call>
45    where
46        Host::Value<'call>: Clone,
47    {
48        self.context.value.clone()
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::{ProviderValueContext, Value};
55    use crate::host::{HostTypeParameter, HostValue, HostValueFamily, HostValueToken};
56
57    #[test]
58    fn provider_value_preserves_the_exact_call_scoped_host_handle() {
59        type Parameter = HostTypeParameter<0>;
60        let host = HostValue::<Parameter>::new(HostValueToken {
61            family: HostValueFamily::String,
62            index: 4,
63        });
64        let value = Value::<Parameter, ProviderValueContext<'_, Parameter>>::from_host(host);
65
66        assert_eq!(value.host().token, host.token);
67        assert_eq!(value.into_host().token, host.token);
68    }
69}