title: Rust: How to read a config file at runtime and store in a global struct, accessible across threads?
body: <p>This is my first project in Rust, and I think I'm missing something simple. </p>
  
  <p>I'm attempting to create a simple Web API daemon that will receive POSTs of JSON, parse the JSON, and send an email using credentials provided in a config file.
  90% of that problem has been easy.  I am struggling with "parse the config file at runtime".</p>
  
  <p>I'm successfully use hyper and letter to receive JSON and send emails.  But I'd like this daemon to be configurable on the server, not at build-time (like most Linux / Unix daemons).  I've diligently followed through <a href="https://omarabid.com/rust-intro" rel="noreferrer">here</a>. </p>
  
  <p>I've created a config module, declared a struct, and used <code>lazy_static!{}</code> to store an initial version of the configuration struct.</p>
  
  <p>I think I've boiled my problem down to one core question: How do I read and parse a config file, then <em>clone</em> the values into my struct?  Especially considering the fact that the size of those values can't be known at runtime...</p>
  
  <p>e.g. <code>src/config.rs</code></p>
  
  <pre class="lang-rust prettyprint-override"><code>use std::sync::RwLock;
  use serde::Deserialize;
  use std::fs;
  use std::io::prelude::*;
  
  #[derive(Debug, Deserialize, Clone, Copy)]
  pub struct RimfireCfg {
      pub verbose: u8,
  
      /* web api server config */
      pub listen_address: &amp;'static str,
  
      /* mail server config */
      pub mailserver: &amp;'static str,
      pub port:                u16,
      pub user:       &amp;'static str,
      pub password:   &amp;'static str,
  }
  
  lazy_static! {
      pub static ref CONFIG: RwLock&lt;RimfireCfg&gt; = RwLock::new(
          RimfireCfg {
              verbose: 0,
              listen_address: "127.0.0.1:3000",
              mailserver: "smtp-mail.outlook.com",
              port: 587,
              user: "",
              password: "",
          }
      );
  }
  
  impl RimfireCfg {
      pub fn init() -&gt; Result&lt;(), i32&gt; {
          let mut w = CONFIG.write().unwrap();
  
          /* read the config file */
          let _lcfg: RimfireCfg =
              toml::from_slice(&amp;fs::read("rimfire.toml").unwrap()).unwrap();
  
          // this is clearly wrong ...
          *w.listen_address = _lcfg.listen_address.clone();
          dbg!(*w);
  
          Ok(())
      }
  
      pub fn clone_config() -&gt; RimfireCfg {
          let m = CONFIG.read().unwrap();
  
          *m
      }
  }
  </code></pre>
  
  <p>and <code>src/main.rs</code>:</p>
  
  <pre class="lang-rust prettyprint-override"><code>#[macro_use]
  extern crate lazy_static;
  
  mod config;
  
  use config::RimfireCfg;
  
  fn main() {
      let a = RimfireCfg::clone_config();
  
      dbg!(a);
  
      RimfireCfg::init().unwrap();
  
      let a = RimfireCfg::clone_config();
  
      dbg!(a);
  }
  </code></pre>
  
  <p>Any thoughts?  suggestions?</p>