Implement the Context Trait
A more advanced guide for when you want to use your own structs as a source for variables.
So far, we’ve used environment variables and HashMap
. But what if your data is
in a custom struct? You could convert it to a HashMap
first, but that’s extra
work and a bit messy.
A better way is to teach envfmt
how to read from your struct directly. You can
do this by implementing the Context
trait. This is the key to making envfmt
super flexible.
The Context
Trait
The trait itself is really simple. It looks like this:
pub trait Context {
fn get(&self, key: &str) -> Option<String>;
}
It only has one method, get
. This method takes a variable name (like
"RPC_URL"
) and should return Some(String)
if the variable exists, or None
if it doesn’t.
Example: A Custom Ethereum Config Struct
Let’s say you have a config struct for your Ethereum application that you load from a file.
struct Config {
network: String,
chain_id: u64,
api_key: String,
}
We want to use an instance of Config
directly with format_with()
. To do
that, we need to implement Context
for it.
use envfmt::Context;
struct Config {
network: String,
chain_id: u64,
api_key: String,
}
// Here's the implementation
impl Context for Config {
fn get(&self, key: &str) -> Option<String> {
match key {
"NETWORK" => Some(self.network.clone()),
"CHAIN_ID" => Some(self.chain_id.to_string()),
"API_KEY" => Some(self.api_key.clone()),
_ => None, // For any other key, we don't have a value
}
}
}
In the get
method, we just use a match
statement. If the key
is one we
know, we return its value wrapped in Some()
. Notice that we have to convert
the chain_id
number to a String
. If the key is unknown, we return None
.
Putting It All Together
Now we can use our Config
struct with format_with()
just like we did with a
HashMap
.
fn main() {
let config = Config {
network: "mainnet".to_string(),
chain_id: 1,
api_key: "my-secret-key".to_string(),
};
let template = "https://eth-${NETWORK}.g.alchemy.com/v2/$API_KEY (Chain ID: $CHAIN_ID)";
let rpc_url = format_with(template, &config).unwrap();
println!("{}", rpc_url);
}
When you run this, the output will be:
https://eth-mainnet.g.alchemy.com/v2/my-secret-key (Chain ID: 1)
And that’s it. By implementing one small trait, you can make envfmt
work with
any of your own data structures.