freya_core/lifecycle/
context.rs1use std::{
2 any::TypeId,
3 rc::Rc,
4};
5
6use crate::{
7 current_context::CurrentContext,
8 prelude::use_hook,
9 scope_id::ScopeId,
10};
11
12pub fn provide_context<T: Clone + 'static>(value: T) {
13 provide_context_for_scope_id(value, None)
14}
15
16pub fn provide_root_context<T: Clone + 'static>(value: T) {
21 provide_context_for_scope_id(value, Some(ScopeId::ROOT))
22}
23
24pub fn provide_context_for_scope_id<T: Clone + 'static>(
25 value: T,
26 scope_id: impl Into<Option<ScopeId>>,
27) {
28 CurrentContext::with(|context| {
29 let mut scopes_storages = context.scopes_storages.borrow_mut();
30 let scopes_storage = scopes_storages
31 .get_mut(&scope_id.into().unwrap_or(context.scope_id))
32 .unwrap();
33 let type_id = TypeId::of::<T>();
34 scopes_storage.contexts.insert(type_id, Rc::new(value));
35 })
36}
37
38pub fn try_consume_context<T: Clone + 'static>() -> Option<T> {
39 try_consume_context_from_scope_id(None)
40}
41
42pub fn try_consume_own_context<T: Clone + 'static>() -> Option<T> {
44 CurrentContext::with(|context| {
45 let scopes_storages = context.scopes_storages.borrow();
46 let scopes_storage = scopes_storages.get(&context.scope_id)?;
47 let type_id = TypeId::of::<T>();
48 scopes_storage
49 .contexts
50 .get(&type_id)?
51 .downcast_ref::<T>()
52 .cloned()
53 })
54}
55
56pub fn try_consume_root_context<T: Clone + 'static>() -> Option<T> {
57 try_consume_context_from_scope_id(Some(ScopeId::ROOT))
58}
59
60pub fn consume_context<T: Clone + 'static>() -> T {
61 try_consume_context_from_scope_id(None)
62 .unwrap_or_else(|| panic!("Context <{}> was not found.", std::any::type_name::<T>()))
63}
64
65pub fn consume_root_context<T: Clone + 'static>() -> T {
66 try_consume_context_from_scope_id(Some(ScopeId::ROOT)).unwrap_or_else(|| {
67 panic!(
68 "Root context <{}> was not found.",
69 std::any::type_name::<T>()
70 )
71 })
72}
73
74pub fn try_consume_context_from_scope_id<T: Clone + 'static>(
75 scope_id: Option<ScopeId>,
76) -> Option<T> {
77 CurrentContext::with(|context| {
78 let scopes_storages = context.scopes_storages.borrow_mut();
79
80 let mut ladder = vec![scope_id.unwrap_or(context.scope_id)];
81
82 let type_id = TypeId::of::<T>();
83
84 while let Some(scope_id) = ladder.pop() {
85 let scopes_storage = scopes_storages.get(&scope_id)?;
86
87 if let Some(context) = scopes_storage.contexts.get(&type_id) {
88 return context.downcast_ref::<T>().cloned();
89 } else if let Some(parent_scope_id) = scopes_storage.parent_id {
90 ladder.push(parent_scope_id);
91 }
92 }
93
94 None
95 })
96}
97
98pub fn use_provide_context<T: Clone + 'static>(init: impl FnOnce() -> T) -> T {
101 use_hook(|| {
102 let ctx = init();
103 provide_context(ctx.clone());
104 ctx
105 })
106}
107
108pub fn use_provide_root_context<T: Clone + 'static>(init: impl FnOnce() -> T) -> T {
113 use_hook(|| {
114 let ctx = init();
115 provide_root_context(ctx.clone());
116 ctx
117 })
118}
119
120pub fn use_consume<T: Clone + 'static>() -> T {
122 use_hook(|| consume_context())
123}
124
125pub fn use_try_consume<T: Clone + 'static>() -> Option<T> {
127 use_hook(|| try_consume_context())
128}