use std::env;
const DEFAULT_API_URL: &'static str = "https://retdec.com/service/api";
#[derive(Clone, Debug)]
pub struct Settings {
api_key: Option<String>,
api_url: String,
}
impl Settings {
pub fn new() -> Self {
Self::default()
}
pub fn with_api_key<K: Into<String>>(mut self, new_api_key: K) -> Self {
self.set_api_key(new_api_key);
self
}
pub fn with_api_url<U: Into<String>>(mut self, new_api_url: U) -> Self {
self.set_api_url(new_api_url);
self
}
pub fn set_api_key<K: Into<String>>(&mut self, new_api_key: K) {
self.api_key = Some(new_api_key.into());
}
pub fn set_api_url<U: Into<String>>(&mut self, new_api_url: U) {
self.api_url = Self::normalize_api_url(new_api_url.into());
}
pub fn api_key(&self) -> Option<&str> {
self.api_key.as_ref().map(String::as_str)
}
pub fn api_url(&self) -> &str {
&self.api_url
}
fn default_api_key() -> Option<String> {
match env::var("RETDEC_API_KEY") {
Ok(api_key) => Some(api_key),
Err(_) => None,
}
}
fn default_api_url() -> String {
match env::var("RETDEC_API_URL") {
Ok(api_url) => Self::normalize_api_url(api_url),
Err(_) => DEFAULT_API_URL.to_string(),
}
}
fn normalize_api_url(mut api_url: String) -> String {
if api_url.ends_with('/') {
api_url.pop();
}
api_url
}
}
impl Default for Settings {
fn default() -> Settings {
Settings {
api_key: Self::default_api_key(),
api_url: Self::default_api_url(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn settings_new_returns_settings_with_default_values() {
let s = Settings::new();
match env::var("RETDEC_API_KEY") {
Ok(api_key) => assert_eq!(s.api_key(), Some(api_key.as_str())),
Err(_) => assert!(s.api_key().is_none()),
}
match env::var("RETDEC_API_URL") {
Ok(mut api_url) => {
if api_url.ends_with('/') {
api_url.pop();
}
assert_eq!(s.api_url(), &api_url)
}
Err(_) => assert_eq!(s.api_url(), DEFAULT_API_URL),
}
}
#[test]
fn new_returns_same_value_as_default() {
let s1 = Settings::new();
let s2 = Settings::default();
assert_eq!(s1.api_key(), s2.api_key());
assert_eq!(s1.api_url(), s2.api_url());
}
#[test]
fn settings_api_key_returns_correct_value_after_being_set() {
let mut s = Settings::new();
s.set_api_key("KEY");
assert_eq!(s.api_key(), Some("KEY"));
}
#[test]
fn settings_api_url_returns_correct_value_after_being_set() {
let mut s = Settings::new();
s.set_api_url("URL");
assert_eq!(s.api_url(), "URL");
}
#[test]
fn settings_trailing_slash_is_removed_from_api_url() {
let s = Settings::new()
.with_api_url(format!("{}/", DEFAULT_API_URL));
assert_eq!(s.api_url(), DEFAULT_API_URL);
}
#[test]
fn settings_can_set_all_attributes_at_once_via_with_methods() {
let s = Settings::new()
.with_api_key("KEY")
.with_api_url("URL");
assert_eq!(s.api_key(), Some("KEY"));
assert_eq!(s.api_url(), "URL");
}
}