use std::path::PathBuf;
use anyhow::Result;
use iroh::{EndpointAddr, EndpointId};
use iroh_blobs::Hash;
use crate::core::peers::PeerStore;
pub fn default_data_dir() -> PathBuf {
dirs_next::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join(".ringdrop")
}
pub fn parse_peer_id(s: &str) -> Result<EndpointId> {
s.parse()
.map_err(|e| anyhow::anyhow!("invalid peer id: {e}"))
}
pub(crate) fn relay_only_addr(full: EndpointAddr) -> EndpointAddr {
full.relay_urls()
.fold(EndpointAddr::new(full.id), |a, url| {
a.with_relay_url(url.clone())
})
}
pub(crate) fn format_peer_entry(peer: &EndpointId, nick: Option<&str>) -> String {
match nick {
Some(n) => format!("{peer} ({n})"),
None => peer.to_string(),
}
}
pub(crate) fn display_peer(peer: &EndpointId, store: &PeerStore) -> String {
let nick = store.get(peer).ok().flatten().flatten();
format_peer_entry(peer, nick.as_deref())
}
pub fn parse_hash(s: &str) -> Result<Hash> {
s.parse().map_err(|e| anyhow::anyhow!("invalid hash: {e}"))
}
#[cfg(test)]
mod tests {
use iroh::SecretKey;
use iroh_blobs::Hash;
use super::*;
#[test]
fn parse_peer_id_accepts_valid_key_string() {
let id = SecretKey::generate().public();
let s = id.to_string();
assert_eq!(parse_peer_id(&s).unwrap(), id);
}
#[test]
fn parse_peer_id_rejects_garbage() {
let err = parse_peer_id("not-a-valid-peer-id").unwrap_err();
assert!(err.to_string().contains("invalid peer id"));
}
#[test]
fn parse_hash_accepts_valid_hex() {
let hash = Hash::from_bytes([0x42; 32]);
let hex = hash.to_string();
assert_eq!(parse_hash(&hex).unwrap(), hash);
}
#[test]
fn parse_hash_rejects_invalid_hex_chars() {
let err = parse_hash(&"z".repeat(64)).unwrap_err();
assert!(err.to_string().contains("invalid hash"));
}
#[test]
fn relay_only_addr_preserves_node_id_when_no_relay() {
let id = SecretKey::generate().public();
let addr = EndpointAddr::new(id);
let result = relay_only_addr(addr);
assert_eq!(result.id, id);
}
#[test]
fn relay_only_addr_preserves_relay_url() {
use iroh::RelayUrl;
let id = SecretKey::generate().public();
let url: RelayUrl = "https://relay.example.com".parse().unwrap();
let addr = EndpointAddr::new(id).with_relay_url(url.clone());
let result = relay_only_addr(addr);
assert_eq!(result.id, id);
assert!(result.relay_urls().any(|u| u == &url));
}
#[test]
fn format_peer_entry_without_nickname_returns_raw_id() {
let id = SecretKey::generate().public();
let result = format_peer_entry(&id, None);
assert_eq!(result, id.to_string());
}
#[test]
fn format_peer_entry_with_nickname_includes_nickname_in_parens() {
let id = SecretKey::generate().public();
let result = format_peer_entry(&id, Some("alice"));
assert!(result.contains(&id.to_string()));
assert!(result.contains("(alice)"));
}
}