I am unsure what the issue is, regarding this error. I cannot seem to find information about the reason a function is expected to be Config (my struct?):
error[E0308]: mismatched types
--> src/config.rs:57:2
|
57 | config_read()
| ^^^^^^^^^^^^^ expected `Config`, found `()`
config.rs:
use std::fs;
use std::sync::LazyLock;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct Config {
pub cert: Cert,
pub key: Key,
}
#[derive(Debug, Deserialize)]
pub struct Cert {
pub principle: String,
pub validity: String,
}
#[derive(Debug, Deserialize)]
pub struct Key {
pub ca_priv_key: String,
pub user_dir: String,
pub cert_serial: String,
}
pub fn config_read() {
// Get the value of the "$HOME" environment variable.
let home_env = std::env::var("HOME").unwrap();
// Append the configuration-file directory to the "$HOME" environment-variable value.
static config_dir: &str = "/.config/signatory";
// Append the configuration-file filename to the configuration-file directory.
let config_file = [home_env.clone(), config_dir.to_string(), "/config.toml".to_string()].join("");
// Parse the keys inside of the configuration-file.
let config_file_parse = fs::read_to_string(&config_file).unwrap();
let config: Config = toml::from_str(&config_file_parse).unwrap();
// Set the values of the OpenSSH-generation for-loop to the values of the configuration-file keys.
let ca_priv_key = config.key.ca_priv_key;
let user_dir = config.key.user_dir;
let cert_serial = config.key.cert_serial;
let principle = config.cert.principle;
let validity = config.cert.validity;
}
// Allow the configuration-file structs to be referenced in the OpenSSH-certificate generation code (see generate.rs).
pub static CONFIG: LazyLock<Config> = LazyLock::new (|| {
config_read()
});
You meant to return Config from the function:
pub fn config_read() -> Config {
// Get the value of the "$HOME" environment variable.
let home_env = std::env::var("HOME").unwrap();
// Append the configuration-file directory to the "$HOME" environment-variable value.
static config_dir: &str = "/.config/signatory";
// Append the configuration-file filename to the configuration-file directory.
let config_file = [home_env.clone(), config_dir.to_string(), "/config.toml".to_string()].join("");
// Parse the keys inside of the configuration-file.
let config_file_parse = fs::read_to_string(&config_file).unwrap();
return toml::from_str(&config_file_parse).unwrap();
// more idiomatically, `return` and semicolon would be skipped
// a function returns result of its last expression on its own
}
Note that Rust's variables are scoped to where they are declared, so let ca_priv_key = ... only creates it inside config_read to live until the closing brace, and doesn't influence/pass it to any other parts of your program.
There is no action at a distance.
That's a design point of Rust: all state which is required for operation is to be passed explicitly. It allows you to see a function which uses some &Config and see where it's passed from: it will either be an argument or obtained by &*config::CONFIG (which is the same as LazyLock::force(&config::CONFIG)).
These changes solved the issue. I am still trying to wrap my head around how LazyLoad and such work. I knew there was a return value, but didn't understand that I hadn't implemented it. toml::from_str being the return value in the function was something I never thought of.
I was recently made aware that the variables cannot be scoped outside of where they are created, which is the reason I implemented this code; it's an attempt at keeping it as close as possible to what I had, but it could likely be massively improved.
Thank you for the assistance.