@@ -3,13 +3,17 @@ mod source;
3
3
4
4
pub ( crate ) mod deser;
5
5
6
- use std:: { collections:: HashMap , convert:: Infallible } ;
6
+ use std:: {
7
+ cell:: RefCell ,
8
+ collections:: { hash_map:: Entry , HashMap } ,
9
+ convert:: Infallible ,
10
+ } ;
7
11
8
12
pub use registry:: * ;
9
13
use serde:: { de:: DeserializeOwned , Deserialize } ;
10
14
pub use source:: * ;
11
15
12
- use crate :: { sync:: * , Result } ;
16
+ use crate :: { sync:: * , Logger , LoggerBuilder , LoggerParams , Result } ;
13
17
14
18
// TODO: Builder?
15
19
#[ derive( PartialEq , Eq , Hash ) ]
@@ -57,25 +61,78 @@ pub trait Configurable: Sized {
57
61
58
62
// #[derive(Deserialize)]
59
63
// #[serde(deny_unknown_fields)]
60
- // pub(super) struct Logger(#[serde(deserialize_with =
64
+ // struct Logger(#[serde(deserialize_with =
61
65
// "crate::config::deser::logger")] crate::Logger);
62
66
63
- #[ derive( PartialEq , Debug , Deserialize ) ]
67
+ #[ derive( Deserialize ) ]
64
68
#[ serde( deny_unknown_fields) ]
65
- pub ( super ) struct ConfigView {
66
- loggers : HashMap < String , toml:: Value > ,
69
+ struct ConfigView {
70
+ loggers : HashMap < String , LoggerParams > ,
71
+ }
72
+
73
+ #[ derive( Debug , Hash , Eq , PartialEq ) ]
74
+ enum LoggerKind {
75
+ Default ,
76
+ Named ( String ) ,
67
77
}
68
78
69
- #[ derive( PartialEq , Debug ) ]
70
79
pub struct Config {
71
- view : ConfigView , // Stores the config values only, build lazily
80
+ view : ConfigView , // Stores the config values only, build loggers lazily
81
+ built : RefCell < HashMap < LoggerKind , Weak < Logger > > > ,
82
+ }
83
+ // TODO: But only build once! For later acquires, return the built `Arc<Logger>`
84
+ // Stores `Weak`?
85
+
86
+ impl Config {
87
+ pub fn acquire_default_logger ( & self ) -> Option < Result < Arc < Logger > > > {
88
+ self . acquire_logger_inner ( LoggerKind :: Default )
89
+ }
90
+
91
+ pub fn acquire_logger < S > ( & self , name : S ) -> Option < Result < Arc < Logger > > >
92
+ where
93
+ S : AsRef < str > ,
94
+ {
95
+ self . acquire_logger_inner ( LoggerKind :: Named ( name. as_ref ( ) . into ( ) ) )
96
+ }
97
+ }
98
+
99
+ impl Config {
100
+ fn acquire_logger_inner ( & self , logger_kind : LoggerKind ) -> Option < Result < Arc < Logger > > > {
101
+ let logger_name = match & logger_kind {
102
+ LoggerKind :: Default => "default" ,
103
+ LoggerKind :: Named ( name) => name,
104
+ } ;
105
+ let logger_params = self . view . loggers . get ( logger_name) ?;
106
+
107
+ // TODO: Factually unnecessary clone in the argument of `build_config`, could be
108
+ // avoided with some effort
109
+ Some ( ( || match self . built . borrow_mut ( ) . entry ( logger_kind) {
110
+ Entry :: Occupied ( mut entry) => match entry. get ( ) . upgrade ( ) {
111
+ None => {
112
+ let new = Arc :: new ( LoggerBuilder :: build_config ( logger_params. clone ( ) ) ?) ;
113
+ entry. insert ( Arc :: downgrade ( & new) ) ;
114
+ Ok ( new)
115
+ }
116
+ Some ( built) => Ok ( built) ,
117
+ } ,
118
+ Entry :: Vacant ( entry) => {
119
+ let new = Arc :: new ( LoggerBuilder :: build_config ( logger_params. clone ( ) ) ?) ;
120
+ entry. insert ( Arc :: downgrade ( & new) ) ;
121
+ Ok ( new)
122
+ }
123
+ } ) ( ) )
124
+ }
72
125
}
73
126
127
+ // TODO: temp code
74
128
impl Config {
75
129
// TODO: Remember to remove me
76
130
pub fn new_for_test ( inputs : & str ) -> Result < Self > {
77
131
let view = toml:: from_str ( inputs) . unwrap ( ) ;
78
- Ok ( Self { view } )
132
+ Ok ( Self {
133
+ view,
134
+ built : RefCell :: new ( HashMap :: new ( ) ) ,
135
+ } )
79
136
}
80
137
}
81
138
0 commit comments