#[allow(dead_code)]
pub const TARGET_PREFIX: &str = "wasi_pg_client";
pub const TARGET_TRANSPORT: &str = "wasi_pg_client::transport";
pub const TARGET_CONNECTION: &str = "wasi_pg_client::connection";
pub const TARGET_AUTH: &str = "wasi_pg_client::auth";
pub const TARGET_QUERY: &str = "wasi_pg_client::query";
pub const TARGET_TRANSACTION: &str = "wasi_pg_client::transaction";
pub const TARGET_COPY: &str = "wasi_pg_client::copy";
pub const TARGET_NOTIFICATION: &str = "wasi_pg_client::notification";
#[allow(dead_code)]
pub const TARGET_POOL: &str = "wasi_pg_client::pool";
pub const TARGET_RECONNECT: &str = "wasi_pg_client::reconnect";
pub const TARGET_PROTOCOL: &str = "wasi_pg_client::protocol";
pub const TARGET_CANCEL: &str = "wasi_pg_client::cancel";
pub fn truncate_str(s: &str, max_len: usize) -> String {
if s.len() <= max_len {
s.to_string()
} else {
let mut end = max_len;
while !s.is_char_boundary(end) && end > 0 {
end -= 1;
}
format!("{}...", &s[..end])
}
}
#[allow(dead_code)]
pub fn redact_connection_string(s: &str) -> String {
if let Some(start) = s.find("://") {
let after_scheme = &s[start + 3..];
let authority_end = after_scheme.find('/').unwrap_or(after_scheme.len());
let authority = &after_scheme[..authority_end];
if let Some(at_pos) = authority.rfind('@') {
let user_part = &authority[..at_pos];
if let Some(colon_pos) = user_part.find(':') {
let before = &s[..start + 3 + colon_pos + 1];
let after = &s[start + 3 + at_pos..];
return format!("{}***{}", before, after);
}
}
}
s.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_truncate_str_short() {
assert_eq!(truncate_str("hi", 10), "hi");
}
#[test]
fn test_truncate_str_exact() {
assert_eq!(truncate_str("hello", 5), "hello");
}
#[test]
fn test_truncate_str_long() {
assert_eq!(truncate_str("hello world", 5), "hello...");
}
#[test]
fn test_truncate_str_empty() {
assert_eq!(truncate_str("", 5), "");
}
#[test]
fn test_truncate_str_zero_max() {
assert_eq!(truncate_str("hello", 0), "...");
}
#[test]
fn test_truncate_str_multibyte() {
let s = "café résumé";
let truncated = truncate_str(s, 5);
assert!(truncated.ends_with("...") || truncated.len() <= 8);
assert!(std::str::from_utf8(truncated.as_bytes()).is_ok());
}
#[test]
fn test_redact_connection_string_with_password() {
let input = "postgresql://user:secret@host:5432/db";
let output = redact_connection_string(input);
assert_eq!(output, "postgresql://user:***@host:5432/db");
assert!(!output.contains("secret"));
}
#[test]
fn test_redact_connection_string_no_password() {
let input = "postgresql://user@host:5432/db";
let output = redact_connection_string(input);
assert_eq!(output, "postgresql://user@host:5432/db");
}
#[test]
fn test_redact_connection_string_no_scheme() {
let input = "host=localhost port=5432";
let output = redact_connection_string(input);
assert_eq!(output, "host=localhost port=5432");
}
#[test]
fn test_redact_connection_string_complex_password() {
let input = "postgresql://admin:p@ss:w0rd@db.example.com:5432/mydb";
let output = redact_connection_string(input);
assert_eq!(output, "postgresql://admin:***@db.example.com:5432/mydb");
assert!(!output.contains("p@ss:w0rd"));
}
#[test]
fn test_target_constants_are_prefixed() {
assert!(TARGET_TRANSPORT.starts_with(TARGET_PREFIX));
assert!(TARGET_CONNECTION.starts_with(TARGET_PREFIX));
assert!(TARGET_AUTH.starts_with(TARGET_PREFIX));
assert!(TARGET_QUERY.starts_with(TARGET_PREFIX));
assert!(TARGET_TRANSACTION.starts_with(TARGET_PREFIX));
assert!(TARGET_COPY.starts_with(TARGET_PREFIX));
assert!(TARGET_NOTIFICATION.starts_with(TARGET_PREFIX));
assert!(TARGET_POOL.starts_with(TARGET_PREFIX));
assert!(TARGET_RECONNECT.starts_with(TARGET_PREFIX));
assert!(TARGET_PROTOCOL.starts_with(TARGET_PREFIX));
assert!(TARGET_CANCEL.starts_with(TARGET_PREFIX));
}
}