#![deny(unsafe_code)]
#![deny(rust_2018_idioms, clippy::disallowed_methods, clippy::disallowed_types)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, allow(unused_attributes))]
pub mod api;
mod common;
#[cfg(feature = "config")]
mod config;
#[cfg(feature = "naming")]
mod naming;
#[allow(dead_code)]
#[path = ""]
mod nacos_proto {
#[path = "_.rs"]
pub mod v2;
}
use crate::api::constants::ENV_NACOS_CLIENT_PROPS_FILE_PATH;
use std::collections::HashMap;
static PROPERTIES: std::sync::LazyLock<HashMap<String, String>> = std::sync::LazyLock::new(|| {
let env_file_path = std::env::var(ENV_NACOS_CLIENT_PROPS_FILE_PATH).ok();
let _ = env_file_path.as_ref().map(|file_path| {
dotenvy::from_path(std::path::Path::new(file_path)).inspect_err(|_e| {
let _ = dotenvy::dotenv();
})
});
dotenvy::dotenv().ok();
dotenvy::vars().collect::<HashMap<String, String>>()
});
pub(crate) mod properties {
use crate::PROPERTIES;
pub(crate) fn get_value_option<Key>(key: Key) -> Option<String>
where
Key: AsRef<str>,
{
PROPERTIES.get(key.as_ref()).cloned()
}
pub(crate) fn get_value<Key, Default>(key: Key, default: Default) -> String
where
Key: AsRef<str>,
Default: AsRef<str>,
{
PROPERTIES
.get(key.as_ref())
.map_or(default.as_ref().to_string(), |value| value.to_string())
}
pub(crate) fn get_value_u32<Key>(key: Key, default: u32) -> u32
where
Key: AsRef<str>,
{
PROPERTIES.get(key.as_ref()).map_or(default, |value| {
value.to_string().parse::<u32>().unwrap_or(default)
})
}
pub(crate) fn get_value_bool<Key>(key: Key, default: bool) -> bool
where
Key: AsRef<str>,
{
PROPERTIES.get(key.as_ref()).map_or(default, |value| {
value.to_string().parse::<bool>().unwrap_or(default)
})
}
}
#[cfg(test)]
mod tests {
use prost_types::Any;
use std::collections::HashMap;
use crate::nacos_proto::v2::Metadata;
use crate::nacos_proto::v2::Payload;
#[test]
fn it_works_nacos_proto() {
let body = Any {
type_url: String::new(),
value: Vec::from("{\"cluster\":\"DEFAULT\",\"healthyOnly\":true}"),
};
let metadata = Metadata {
r#type: String::from("com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest"),
client_ip: String::from("127.0.0.1"),
headers: HashMap::new(),
};
let payload = Payload {
metadata: Some(metadata),
body: Some(body),
};
assert_eq!(
payload
.metadata
.expect("Metadata should exist after checking it's some")
.r#type,
"com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest"
);
assert_eq!(
payload
.body
.expect("Body should exist after checking it's some")
.value,
Vec::from("{\"cluster\":\"DEFAULT\",\"healthyOnly\":true}")
);
}
}
#[cfg(test)]
mod test_props {
use crate::api::constants::ENV_NACOS_CLIENT_NAMING_PUSH_EMPTY_PROTECTION;
use crate::properties::{get_value, get_value_bool, get_value_u32};
#[test]
fn test_get_value() {
let v = get_value("ENV_TEST", "TEST");
assert_eq!(v, "TEST");
}
#[test]
fn test_get_value_bool() {
let v = get_value_bool(ENV_NACOS_CLIENT_NAMING_PUSH_EMPTY_PROTECTION, true);
assert!(v);
}
#[test]
fn test_get_value_u32() {
let not_exist_key = "MUST_NOT_EXIST";
let v = get_value_u32(not_exist_key, 91);
assert_eq!(v, 91);
}
}
#[cfg(test)]
mod test_config {
use std::sync::Once;
use tracing::metadata::LevelFilter;
static LOGGER_INIT: Once = Once::new();
pub(crate) fn setup_log() {
LOGGER_INIT.call_once(|| {
let _ = tracing_subscriber::fmt()
.with_thread_names(true)
.with_file(true)
.with_level(true)
.with_line_number(true)
.with_thread_ids(true)
.with_max_level(LevelFilter::INFO)
.try_init();
});
}
}