2424//! [build]
2525//! src = "out"
2626//!
27- //! [other-table.foo ]
27+ //! [preprocessor.my-preprocessor ]
2828//! bar = 123
2929//! "#;
3030//!
3131//! // load the `Config` from a toml string
3232//! let mut cfg = Config::from_str(src)?;
3333//!
3434//! // retrieve a nested value
35- //! let bar = cfg.get("other-table.foo. bar").cloned() ;
36- //! assert_eq!(bar, Some(Value::Integer( 123) ));
35+ //! let bar = cfg.get::<i32>("preprocessor.my-preprocessor. bar")? ;
36+ //! assert_eq!(bar, Some(123));
3737//!
3838//! // Set the `output.html.theme` directory
39- //! assert!(cfg.get("output.html").is_none());
39+ //! assert!(cfg.get::<Value> ("output.html")? .is_none());
4040//! cfg.set("output.html.theme", "./themes");
4141//!
4242//! // then load it again, automatically deserializing to a `PathBuf`.
43- //! let got: Option<PathBuf> = cfg.get_deserialized_opt ("output.html.theme")?;
43+ //! let got = cfg.get ("output.html.theme")?;
4444//! assert_eq!(got, Some(PathBuf::from("./themes")));
4545//! # Ok(())
4646//! # }
4747//! # run().unwrap()
4848//! ```
4949
50+ use crate :: utils:: TomlExt ;
5051use crate :: utils:: log_backtrace;
51- use crate :: utils:: toml_ext:: TomlExt ;
52- use anyhow:: { Context , Error , Result , bail} ;
52+ use anyhow:: { Context , Error , Result } ;
5353use log:: { debug, trace, warn} ;
5454use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
5555use std:: collections:: HashMap ;
@@ -154,18 +154,28 @@ impl Config {
154154 }
155155 }
156156
157- /// Fetch an arbitrary item from the `Config` as a `toml::Value` .
157+ /// Get a value from the configuration .
158158 ///
159- /// You can use dotted indices to access nested items (e.g.
160- /// `output.html.playground` will fetch the "playground" out of the html output
161- /// table).
162- pub fn get ( & self , key : & str ) -> Option < & Value > {
163- self . rest . read ( key)
164- }
165-
166- /// Fetch a value from the `Config` so you can mutate it.
167- pub fn get_mut ( & mut self , key : & str ) -> Option < & mut Value > {
168- self . rest . read_mut ( key)
159+ /// This fetches a value from the book configuration. The key can have
160+ /// dotted indices to access nested items (e.g. `output.html.playground`
161+ /// will fetch the "playground" out of the html output table).
162+ ///
163+ /// This does not have access to the [`Config::book`], [`Config::build`],
164+ /// or [`Config::rust`] fields.
165+ ///
166+ /// Returns `Ok(None)` if the field is not set.
167+ ///
168+ /// Returns `Err` if it fails to deserialize.
169+ pub fn get < ' de , T : Deserialize < ' de > > ( & self , name : & str ) -> Result < Option < T > > {
170+ self . rest
171+ . read ( name)
172+ . map ( |value| {
173+ value
174+ . clone ( )
175+ . try_into ( )
176+ . with_context ( || "Couldn't deserialize the value" )
177+ } )
178+ . transpose ( )
169179 }
170180
171181 /// Convenience method for getting the html renderer's configuration.
@@ -177,7 +187,7 @@ impl Config {
177187 #[ doc( hidden) ]
178188 pub fn html_config ( & self ) -> Option < HtmlConfig > {
179189 match self
180- . get_deserialized_opt ( "output.html" )
190+ . get ( "output.html" )
181191 . with_context ( || "Parsing configuration [output.html]" )
182192 {
183193 Ok ( Some ( config) ) => Some ( config) ,
@@ -189,35 +199,12 @@ impl Config {
189199 }
190200 }
191201
192- /// Deprecated, use get_deserialized_opt instead.
193- #[ deprecated = "use get_deserialized_opt instead" ]
194- pub fn get_deserialized < ' de , T : Deserialize < ' de > , S : AsRef < str > > ( & self , name : S ) -> Result < T > {
195- let name = name. as_ref ( ) ;
196- match self . get_deserialized_opt ( name) ? {
197- Some ( value) => Ok ( value) ,
198- None => bail ! ( "Key not found, {:?}" , name) ,
199- }
200- }
201-
202- /// Convenience function to fetch a value from the config and deserialize it
203- /// into some arbitrary type.
204- pub fn get_deserialized_opt < ' de , T : Deserialize < ' de > , S : AsRef < str > > (
205- & self ,
206- name : S ,
207- ) -> Result < Option < T > > {
208- let name = name. as_ref ( ) ;
209- self . get ( name)
210- . map ( |value| {
211- value
212- . clone ( )
213- . try_into ( )
214- . with_context ( || "Couldn't deserialize the value" )
215- } )
216- . transpose ( )
217- }
218-
219202 /// Set a config key, clobbering any existing values along the way.
220203 ///
204+ /// The key can have dotted indices for nested items (e.g.
205+ /// `output.html.playground` will set the "playground" in the html output
206+ /// table).
207+ ///
221208 /// The only way this can fail is if we can't serialize `value` into a
222209 /// `toml::Value`.
223210 pub fn set < S : Serialize , I : AsRef < str > > ( & mut self , index : I , value : S ) -> Result < ( ) > {
@@ -239,18 +226,6 @@ impl Config {
239226 Ok ( ( ) )
240227 }
241228
242- /// Get the table associated with a particular renderer.
243- pub fn get_renderer < I : AsRef < str > > ( & self , index : I ) -> Option < & Table > {
244- let key = format ! ( "output.{}" , index. as_ref( ) ) ;
245- self . get ( & key) . and_then ( Value :: as_table)
246- }
247-
248- /// Get the table associated with a particular preprocessor.
249- pub fn get_preprocessor < I : AsRef < str > > ( & self , index : I ) -> Option < & Table > {
250- let key = format ! ( "preprocessor.{}" , index. as_ref( ) ) ;
251- self . get ( & key) . and_then ( Value :: as_table)
252- }
253-
254229 fn from_legacy ( mut table : Value ) -> Config {
255230 let mut cfg = Config :: default ( ) ;
256231
@@ -1021,32 +996,16 @@ mod tests {
1021996 } ;
1022997
1023998 let cfg = Config :: from_str ( src) . unwrap ( ) ;
1024- let got: RandomOutput = cfg. get_deserialized_opt ( "output.random" ) . unwrap ( ) . unwrap ( ) ;
999+ let got: RandomOutput = cfg. get ( "output.random" ) . unwrap ( ) . unwrap ( ) ;
10251000
10261001 assert_eq ! ( got, should_be) ;
10271002
1028- let got_baz: Vec < bool > = cfg
1029- . get_deserialized_opt ( "output.random.baz" )
1030- . unwrap ( )
1031- . unwrap ( ) ;
1003+ let got_baz: Vec < bool > = cfg. get ( "output.random.baz" ) . unwrap ( ) . unwrap ( ) ;
10321004 let baz_should_be = vec ! [ true , true , false ] ;
10331005
10341006 assert_eq ! ( got_baz, baz_should_be) ;
10351007 }
10361008
1037- #[ test]
1038- fn mutate_some_stuff ( ) {
1039- // really this is just a sanity check to make sure the borrow checker
1040- // is happy...
1041- let src = COMPLEX_CONFIG ;
1042- let mut config = Config :: from_str ( src) . unwrap ( ) ;
1043- let key = "output.html.playground.editable" ;
1044-
1045- assert_eq ! ( config. get( key) . unwrap( ) , & Value :: Boolean ( true ) ) ;
1046- * config. get_mut ( key) . unwrap ( ) = Value :: Boolean ( false ) ;
1047- assert_eq ! ( config. get( key) . unwrap( ) , & Value :: Boolean ( false ) ) ;
1048- }
1049-
10501009 /// The config file format has slightly changed (metadata stuff is now under
10511010 /// the `book` table instead of being at the top level) so we're adding a
10521011 /// **temporary** compatibility check. You should be able to still load the
@@ -1106,10 +1065,10 @@ mod tests {
11061065 let key = "foo.bar.baz" ;
11071066 let value = "Something Interesting" ;
11081067
1109- assert ! ( cfg. get( key) . is_none( ) ) ;
1068+ assert ! ( cfg. get:: < i32 > ( key) . unwrap ( ) . is_none( ) ) ;
11101069 cfg. set ( key, value) . unwrap ( ) ;
11111070
1112- let got: String = cfg. get_deserialized_opt ( key) . unwrap ( ) . unwrap ( ) ;
1071+ let got: String = cfg. get ( key) . unwrap ( ) . unwrap ( ) ;
11131072 assert_eq ! ( got, value) ;
11141073 }
11151074
@@ -1159,18 +1118,15 @@ mod tests {
11591118 let key = "foo.bar" ;
11601119 let value = "baz" ;
11611120
1162- assert ! ( cfg. get( key) . is_none( ) ) ;
1121+ assert ! ( cfg. get:: < String > ( key) . unwrap ( ) . is_none( ) ) ;
11631122
11641123 let encoded_key = encode_env_var ( key) ;
11651124 // TODO: This is unsafe, and should be rewritten to use a process.
11661125 unsafe { env:: set_var ( encoded_key, value) } ;
11671126
11681127 cfg. update_from_env ( ) ;
11691128
1170- assert_eq ! (
1171- cfg. get_deserialized_opt:: <String , _>( key) . unwrap( ) . unwrap( ) ,
1172- value
1173- ) ;
1129+ assert_eq ! ( cfg. get:: <String >( key) . unwrap( ) . unwrap( ) , value) ;
11741130 }
11751131
11761132 #[ test]
@@ -1180,20 +1136,15 @@ mod tests {
11801136 let value = json ! ( { "array" : [ 1 , 2 , 3 ] , "number" : 13.37 } ) ;
11811137 let value_str = serde_json:: to_string ( & value) . unwrap ( ) ;
11821138
1183- assert ! ( cfg. get( key) . is_none( ) ) ;
1139+ assert ! ( cfg. get:: <serde_json :: Value > ( key) . unwrap ( ) . is_none( ) ) ;
11841140
11851141 let encoded_key = encode_env_var ( key) ;
11861142 // TODO: This is unsafe, and should be rewritten to use a process.
11871143 unsafe { env:: set_var ( encoded_key, value_str) } ;
11881144
11891145 cfg. update_from_env ( ) ;
11901146
1191- assert_eq ! (
1192- cfg. get_deserialized_opt:: <serde_json:: Value , _>( key)
1193- . unwrap( )
1194- . unwrap( ) ,
1195- value
1196- ) ;
1147+ assert_eq ! ( cfg. get:: <serde_json:: Value >( key) . unwrap( ) . unwrap( ) , value) ;
11971148 }
11981149
11991150 #[ test]
0 commit comments