1use std::{
2 any::{Any, TypeId},
3 collections::HashMap,
4 sync::Arc,
5};
6
7use async_context::with_async_context;
8
9use crate::{hook::Hook, Element};
10
11pub struct Provider {
12 value: Arc<dyn Any + Send + Sync>,
13}
14
15impl Provider {
16 pub fn new<T>(value: T) -> Self
17 where
18 T: Send + Sync + 'static,
19 {
20 Self {
21 value: Arc::new(value),
22 }
23 }
24
25 pub fn children<N, E>(self, children: Vec<Element<N, E>>) -> Element<N, E>
26 where
27 N: From<String>,
28 {
29 Element::Provider(self.value, children)
30 }
31}
32
33pub(crate) type ContextMap = Arc<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>;
34
35pub fn use_context<T>() -> Arc<T>
36where
37 T: Clone + Default + 'static,
38{
39 with_async_context(|hook: Option<&Hook>| {
40 if let Some(hook) = hook {
41 hook.context
42 .get(&TypeId::of::<T>())
43 .and_then(|value| value.downcast_ref::<Arc<T>>())
44 .cloned()
45 .unwrap_or(Arc::new(T::default()))
46 } else {
47 Arc::new(T::default())
48 }
49 })
50}
51
52pub fn _get_context() -> ContextMap {
53 with_async_context(|hook: Option<&Hook>| {
54 if let Some(hook) = hook {
55 hook.context.clone()
56 } else {
57 Arc::default()
58 }
59 })
60}