use serde_json::{Map, Value};
use std::net::IpAddr;
pub trait QueryParam {
fn to_param_value(&self) -> Option<String>;
}
impl QueryParam for String {
fn to_param_value(&self) -> Option<String> {
Some(self.clone())
}
}
impl QueryParam for str {
fn to_param_value(&self) -> Option<String> {
Some(self.to_string())
}
}
impl<T: QueryParam> QueryParam for Option<T> {
fn to_param_value(&self) -> Option<String> {
self.as_ref().and_then(|v| v.to_param_value())
}
}
macro_rules! impl_query_param_for_primitive {
($($t:ty),*) => {
$(
impl QueryParam for $t {
fn to_param_value(&self) -> Option<String> {
Some(self.to_string())
}
}
)*
};
}
impl_query_param_for_primitive!(i32, i64, u32, u64, f32, f64, bool, usize);
pub struct NacosUtils;
impl NacosUtils {
pub fn validate_api_code(code: &str) -> Result<(), String> {
if !code.eq("200") {
return Err(format!("Request failed with code: {code}"));
}
Ok(())
}
pub fn build_query_params(params: &[(&str, &dyn QueryParam)]) -> String {
let mut query = vec![];
for (k, v) in params {
if let Some(val) = v.to_param_value() {
query.push(format!("{}={}", k, urlencoding::encode(&val)));
}
}
if query.is_empty() {
String::new()
} else {
format!("?{}", query.join("&"))
}
}
pub fn build_json_body(params: &[(&str, Option<Value>)]) -> Value {
let mut map = Map::new();
for (k, v) in params {
if let Some(val) = v {
map.insert(k.to_string(), val.clone());
}
}
Value::Object(map)
}
pub fn get_local_ip() -> Option<IpAddr> {
let addrs = local_ip_address::list_afinet_netifas().ok()?;
log::debug!("Local network interfaces: {addrs:?}");
for (_name, ip) in addrs {
if ip.is_ipv4() && !ip.is_loopback() {
log::debug!("Local IP address found: {ip}");
return Some(ip);
}
}
None
}
}