use std::convert::TryFrom;
use std::str::FromStr;
use crate::MpesaError;
#[derive(Debug, Clone)]
pub enum Environment {
Production,
Sandbox,
}
pub trait ApiEnvironment: Clone {
fn base_url(&self) -> &str;
fn get_certificate(&self) -> &str;
}
macro_rules! environment_from_string {
($v:expr) => {
match $v {
"production" => Ok(Self::Production),
"sandbox" => Ok(Self::Sandbox),
_ => Err(MpesaError::Message(
"Could not parse the provided environment name",
)),
}
};
}
impl FromStr for Environment {
type Err = MpesaError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
environment_from_string!(s.to_lowercase().as_str())
}
}
impl TryFrom<&str> for Environment {
type Error = MpesaError;
fn try_from(v: &str) -> Result<Self, Self::Error> {
environment_from_string!(v.to_lowercase().as_str())
}
}
impl TryFrom<String> for Environment {
type Error = MpesaError;
fn try_from(v: String) -> Result<Self, Self::Error> {
environment_from_string!(v.to_lowercase().as_str())
}
}
impl ApiEnvironment for Environment {
fn base_url(&self) -> &str {
match self {
Environment::Production => "https://api.safaricom.co.ke",
Environment::Sandbox => "https://sandbox.safaricom.co.ke",
}
}
fn get_certificate(&self) -> &str {
match self {
Environment::Production => include_str!("./certificates/production"),
Environment::Sandbox => include_str!("./certificates/sandbox"),
}
}
}
#[cfg(test)]
mod tests {
use std::convert::TryInto;
use super::*;
#[test]
fn test_valid_string_is_parsed_as_environment() {
let accepted_production_values =
vec!["production", "Production", "PRODUCTION", "prODUctIoN"];
let accepted_sandbox_values = vec!["sandbox", "Sandbox", "SANDBOX", "sanDBoX"];
accepted_production_values.into_iter().for_each(|v| {
let environment: Environment = v.parse().unwrap();
assert_eq!(environment.base_url(), "https://api.safaricom.co.ke");
assert_eq!(
environment.get_certificate(),
include_str!("./certificates/production")
)
});
accepted_sandbox_values.into_iter().for_each(|v| {
let environment: Environment = v.try_into().unwrap();
assert_eq!(environment.base_url(), "https://sandbox.safaricom.co.ke");
assert_eq!(
environment.get_certificate(),
include_str!("./certificates/sandbox")
)
})
}
#[test]
#[should_panic]
fn test_invalid_string_panics() {
let _: Environment = "foo_bar".try_into().unwrap();
}
}