I've already had some success with lazy_static
:
static ref WORD_COUNT_REPORTING_STEP_MUTEX: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
static ref INDEX_NAME: RwLock<String> = RwLock::new("".to_string());
static ref LANGUAGE_DETECTOR: LanguageDetector = LanguageDetectorBuilder::from_all_languages().with_preloaded_language_models().build();
But I'm really scratching my head over what should seemingly be a fairly easy pattern: set something of type Option<T>
to None
and then initialise on discovering that that Option
is indeed None
. If it is discovered that the Option
is Some
, skip the initialisation. After the initialisation block, get the Option
and unwrap()
.
NB the type here is reqwest::blocking::client::Client
.
So far I've got:
lazy_static! {
static ref REQWEST_CLIENT_OPTION: Option<Client> = None;
}
Then, in a function:
...
match &*REQWEST_CLIENT_OPTION {
Some(reqwest_client) => {
info!("reqwest_client_option currently non-None");
},
None => {
info!("reqwest_client_option currently None");
// configuration and build of the client
let es_path = r#"D:\apps\ElasticSearch\elasticsearch-8.6.2\config"#;
set_var("ES_PATH_CONF", &es_path); // from crate tmp_env
let mut buf = Vec::new();
let cert_path = format!(r#"{es_path}\certs\http_ca.crt"#);
let mut cert_file = File::open(cert_path).expect("problem opening certificate file");
cert_file.read_to_end(&mut buf).ok();
let cert = reqwest::Certificate::from_pem(&buf).expect("problem generating certificate"); // delivers cert OK
let reqwest_client = Client::builder()
.add_root_certificate(cert)
.timeout(std::time::Duration::from_millis(5_000))
.build().expect("problem building the request client");
// now I try to set the Option...
let mut static_client = &*REQWEST_CLIENT_OPTION;
info!("static_client type {}", utilities::str_type_of(&static_client));
// static_client type &core::option::Option<reqwest::blocking::client::Client>
static_client = &Some(reqwest_client)
// not now possible to check static_client.
}
}
let reqwest_client = REQWEST_CLIENT_OPTION.as_ref().unwrap();
...
The above is largely guesswork. Needless to say, I've tried innumerable permutations involving *, & and things like let_mut
. I hoped this might work:
*static_client = Some(reqwest_client);
... but this fails: " ^^^^^^^^^^^^^^ static_client
is a &
reference, so the data it refers to cannot be written".
At least the above code compiles OK.
The line "reqwest_client_option currently None" is printed.
But to my disappointment the last line causes a panic:
pyo3_runtime.PanicException: called `Option::unwrap()` on a `None` value
NB I also tried a variant with if let Some(reqwest_client) ...
but ran into the same sorts of problems. This construction would probably be more elegant.
You can use OnceCell
or, since you are making it static, OnceLock
.
For example:
use std::sync::OnceLock;
use reqwest::blocking::Client;
static REQWEST_CLIENT: OnceLock<Client> = OnceLock::new();
fn main(){
let client = REQWEST_CLIENT.get_or_init(|| {
Client::builder()
// other options
.build()
.expect("problem building the reqwest client")
});
// use client
}